From 2dfa1b7e94251acb9c2f69a1cd900bc85f55deb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20Krezovi=C4=87?= Date: Mon, 19 Feb 2024 22:42:56 +0100 Subject: [PATCH] Fix basic auth with encoded characters (#3815) --- .../http/WebClientTransportClientFactory.java | 8 ++++--- .../WebClientTransportClientFactoryTest.java | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/WebClientTransportClientFactory.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/WebClientTransportClientFactory.java index 5a4a20cd73..9a96b25a83 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/WebClientTransportClientFactory.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/WebClientTransportClientFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 the original author or authors. + * Copyright 2017-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,6 +50,7 @@ import org.springframework.web.reactive.function.client.ExchangeFilterFunction; import org.springframework.web.reactive.function.client.ExchangeFilterFunctions; import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.util.UriComponentsBuilder; /** * Provides the custom {@link WebClient.Builder} required by the @@ -58,6 +59,7 @@ * * @author Daniel Lavoie * @author Haytham Mohamed + * @author Armin Krezovic */ public class WebClientTransportClientFactory implements TransportClientFactory { @@ -78,14 +80,14 @@ public EurekaHttpClient newClient(EurekaEndpoint endpoint) { } private WebClient.Builder setUrl(WebClient.Builder builder, String serviceUrl) { - String url = serviceUrl; + String url = UriComponentsBuilder.fromUriString(serviceUrl).userInfo(null).toUriString(); + try { URI serviceURI = new URI(serviceUrl); if (serviceURI.getUserInfo() != null) { String[] credentials = serviceURI.getUserInfo().split(":"); if (credentials.length == 2) { builder.filter(ExchangeFilterFunctions.basicAuthentication(credentials[0], credentials[1])); - url = serviceUrl.replace(credentials[0] + ":" + credentials[1] + "@", ""); } } } diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/WebClientTransportClientFactoryTest.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/WebClientTransportClientFactoryTest.java index b7d2d17baf..16123d5e51 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/WebClientTransportClientFactoryTest.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/WebClientTransportClientFactoryTest.java @@ -18,13 +18,17 @@ import com.netflix.discovery.shared.resolver.DefaultEndpoint; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import reactor.test.StepVerifier; +import org.springframework.http.HttpHeaders; import org.springframework.web.reactive.function.client.WebClient; /** * @author Daniel Lavoie + * @author Armin Krezovic */ class WebClientTransportClientFactoryTest { @@ -45,6 +49,24 @@ void testInvalidUserInfo() { transportClientFatory.newClient(new DefaultEndpoint("http://test@localhost:8761")); } + @Test + void testUserInfoWithEncodedCharacters() { + String encodedBasicAuth = HttpHeaders.encodeBasicAuth("test", "MyPassword@", null); + String expectedAuthHeader = "Basic " + encodedBasicAuth; + String expectedUrl = "http://localhost:8761"; + + WebClientEurekaHttpClient client = (WebClientEurekaHttpClient) transportClientFatory + .newClient(new DefaultEndpoint("http://test:MyPassword%40@localhost:8761")); + + WebClient.Builder builder = client.getWebClient().mutate(); + + StepVerifier.create(builder.filter(((request, next) -> { + Assertions.assertEquals(expectedAuthHeader, request.headers().getFirst(HttpHeaders.AUTHORIZATION)); + Assertions.assertEquals(expectedUrl, request.url().toString()); + return next.exchange(request); + })).build().head().retrieve().toBodilessEntity()).expectError().verify(); + } + @Test void testUserInfo() { transportClientFatory.newClient(new DefaultEndpoint("http://test:test@localhost:8761"));