diff --git a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java index 5be7655f918..3e0a81dc65e 100644 --- a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java +++ b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java @@ -711,13 +711,14 @@ public class HttpHeaders implements MultiValueMap, Serializable /** * Set the value of the {@linkplain #AUTHORIZATION Authorization} header to * Basic Authentication based on the given username and password. - *

Note that Basic Authentication only supports characters in the + *

Note that this method only supports characters in the * {@link StandardCharsets#ISO_8859_1 ISO-8859-1} character set. * @param username the username * @param password the password * @throws IllegalArgumentException if either {@code user} or - * {@code password} contain characters that cannot be encoded to ISO-8859-1. + * {@code password} contain characters that cannot be encoded to ISO-8859-1 * @since 5.1 + * @see #setBasicAuth(String, String, Charset) * @see RFC 7617 */ public void setBasicAuth(String username, String password) { @@ -730,9 +731,9 @@ public class HttpHeaders implements MultiValueMap, Serializable * @param username the username * @param password the password * @param charset the charset to use to convert the credentials into an octet - * sequence. Defaults to {@linkplain StandardCharsets#ISO_8859_1 ISO-8859-1} - * @throws IllegalArgumentException if either {@code user} or - * {@code password} contain characters that cannot be encoded to ISO-8859-1. + * sequence. Defaults to {@linkplain StandardCharsets#ISO_8859_1 ISO-8859-1}. + * @throws IllegalArgumentException if {@code username} or {@code password} + * contains characters that cannot be encoded to the given charset * @since 5.1 * @see RFC 7617 */ @@ -746,8 +747,7 @@ public class HttpHeaders implements MultiValueMap, Serializable CharsetEncoder encoder = charset.newEncoder(); if (!encoder.canEncode(username) || !encoder.canEncode(password)) { throw new IllegalArgumentException( - "Username or password contains characters that cannot be encoded to " + - charset.displayName()); + "Username or password contains characters that cannot be encoded to " + charset.displayName()); } String credentialsString = username + ":" + password; diff --git a/spring-web/src/main/java/org/springframework/http/client/support/BasicAuthenticationInterceptor.java b/spring-web/src/main/java/org/springframework/http/client/support/BasicAuthenticationInterceptor.java new file mode 100644 index 00000000000..0ace9fecfff --- /dev/null +++ b/spring-web/src/main/java/org/springframework/http/client/support/BasicAuthenticationInterceptor.java @@ -0,0 +1,87 @@ +/* + * Copyright 2002-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.http.client.support; + +import java.io.IOException; +import java.nio.charset.Charset; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * {@link ClientHttpRequestInterceptor} to apply a given HTTP Basic Authentication + * username/password pair, unless a custom Authorization header has been set before. + * + * @author Juergen Hoeller + * @since 5.1.1 + * @see HttpHeaders#setBasicAuth + * @see HttpHeaders#AUTHORIZATION + */ +public class BasicAuthenticationInterceptor implements ClientHttpRequestInterceptor { + + private final String username; + + private final String password; + + @Nullable + private final Charset charset; + + + /** + * Create a new interceptor which adds Basic Authentication for the + * given username and password. + * @param username the username to use + * @param password the password to use + * @see HttpHeaders#setBasicAuth(String, String) + */ + public BasicAuthenticationInterceptor(String username, String password) { + this(username, password, null); + } + + /** + * Create a new interceptor which adds Basic Authentication for the + * given username and password, encoded using the specified charset. + * @param username the username to use + * @param password the password to use + * @param charset the charset to use + * @see HttpHeaders#setBasicAuth(String, String, Charset) + */ + public BasicAuthenticationInterceptor(String username, String password, @Nullable Charset charset) { + Assert.doesNotContain(username, ":", "Username must not contain a colon"); + this.username = username; + this.password = password; + this.charset = charset; + } + + + @Override + public ClientHttpResponse intercept( + HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { + + HttpHeaders headers = request.getHeaders(); + if (!headers.containsKey(HttpHeaders.AUTHORIZATION)) { + headers.setBasicAuth(this.username, this.password, this.charset); + } + return execution.execute(request, body); + } + +} diff --git a/spring-web/src/main/java/org/springframework/http/client/support/BasicAuthorizationInterceptor.java b/spring-web/src/main/java/org/springframework/http/client/support/BasicAuthorizationInterceptor.java index b29a412732c..a4ab4e122a6 100644 --- a/spring-web/src/main/java/org/springframework/http/client/support/BasicAuthorizationInterceptor.java +++ b/spring-web/src/main/java/org/springframework/http/client/support/BasicAuthorizationInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -32,7 +32,11 @@ import org.springframework.util.Base64Utils; * * @author Phillip Webb * @since 4.3.1 + * @deprecated as of 5.1.1, in favor of {@link BasicAuthenticationInterceptor} + * which reuses {@link org.springframework.http.HttpHeaders#setBasicAuth}, + * sharing its default charset ISO-8859-1 instead of UTF-8 as used here */ +@Deprecated public class BasicAuthorizationInterceptor implements ClientHttpRequestInterceptor { private final String username; @@ -54,8 +58,8 @@ public class BasicAuthorizationInterceptor implements ClientHttpRequestIntercept @Override - public ClientHttpResponse intercept(HttpRequest request, byte[] body, - ClientHttpRequestExecution execution) throws IOException { + public ClientHttpResponse intercept( + HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { String token = Base64Utils.encodeToString( (this.username + ":" + this.password).getBytes(StandardCharsets.UTF_8)); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctions.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctions.java index 3b5f2210ea1..b6d4056e3d1 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctions.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctions.java @@ -115,11 +115,9 @@ public abstract class ExchangeFilterFunctions { */ @Deprecated public static ExchangeFilterFunction basicAuthentication() { - return (request, next) -> { Credentials cred = (Credentials) request .attribute(BASIC_AUTHENTICATION_CREDENTIALS_ATTRIBUTE).orElse(null); - if (cred != null) { return next.exchange(ClientRequest.from(request) .headers(headers -> headers.setBasicAuth(cred.username, cred.password))