|
|
|
|
@ -20,6 +20,8 @@ import java.io.Serializable;
@@ -20,6 +20,8 @@ import java.io.Serializable;
|
|
|
|
|
import java.net.InetSocketAddress; |
|
|
|
|
import java.net.URI; |
|
|
|
|
import java.nio.charset.Charset; |
|
|
|
|
import java.nio.charset.CharsetEncoder; |
|
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
|
import java.text.DecimalFormat; |
|
|
|
|
import java.text.DecimalFormatSymbols; |
|
|
|
|
import java.time.Instant; |
|
|
|
|
@ -28,6 +30,7 @@ import java.time.ZonedDateTime;
@@ -28,6 +30,7 @@ import java.time.ZonedDateTime;
|
|
|
|
|
import java.time.format.DateTimeFormatter; |
|
|
|
|
import java.time.format.DateTimeParseException; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Base64; |
|
|
|
|
import java.util.Collection; |
|
|
|
|
import java.util.Collections; |
|
|
|
|
import java.util.EnumSet; |
|
|
|
|
@ -38,6 +41,8 @@ import java.util.List;
@@ -38,6 +41,8 @@ import java.util.List;
|
|
|
|
|
import java.util.Locale; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.Set; |
|
|
|
|
import java.util.function.Consumer; |
|
|
|
|
import java.util.function.Supplier; |
|
|
|
|
import java.util.regex.Matcher; |
|
|
|
|
import java.util.regex.Pattern; |
|
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
@ -1564,4 +1569,88 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
@@ -1564,4 +1569,88 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
|
|
|
|
|
return (headers.readOnly ? headers : new HttpHeaders(headers, true)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns a {@code HttpHeaders} consumer that adds Basic Authentication. |
|
|
|
|
* More specifically: a consumer that adds an {@linkplain #AUTHORIZATION |
|
|
|
|
* Authorization} header based on the given username and password. Meant |
|
|
|
|
* to be used in combination with |
|
|
|
|
* {@link org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec#headers(java.util.function.Consumer)}. |
|
|
|
|
* <p>Note that Basic Authentication only supports characters in the |
|
|
|
|
* {@linkplain StandardCharsets#ISO_8859_1 ISO-8859-1} character set. |
|
|
|
|
* |
|
|
|
|
* @param username the username |
|
|
|
|
* @param password the password |
|
|
|
|
* @return a consumer that adds a Basic Authentication header |
|
|
|
|
*/ |
|
|
|
|
public static Consumer<HttpHeaders> basicAuthenticationConsumer(String username,String password) { |
|
|
|
|
return basicAuthenticationConsumer(() -> username, () -> password); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns a {@code HttpHeaders} consumer that adds Basic Authentication. |
|
|
|
|
* More specifically: a consumer that adds an {@linkplain #AUTHORIZATION |
|
|
|
|
* Authorization} header based on the given username and password |
|
|
|
|
* suppliers. Meant to be used in combination with |
|
|
|
|
* {@link org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec#headers(java.util.function.Consumer)}. |
|
|
|
|
* <p>Note that Basic Authentication only supports characters in the |
|
|
|
|
* {@linkplain StandardCharsets#ISO_8859_1 ISO-8859-1} character set. |
|
|
|
|
* |
|
|
|
|
* @param usernameSupplier supplier for the username |
|
|
|
|
* @param passwordSupplier supplier for the password |
|
|
|
|
* @return a consumer that adds a Basic Authentication header |
|
|
|
|
*/ |
|
|
|
|
public static Consumer<HttpHeaders> basicAuthenticationConsumer(Supplier<String> usernameSupplier, |
|
|
|
|
Supplier<String> passwordSupplier) { |
|
|
|
|
|
|
|
|
|
Assert.notNull(usernameSupplier, "Username Supplier must not be null"); |
|
|
|
|
Assert.notNull(passwordSupplier, "Password Supplier must not be null"); |
|
|
|
|
|
|
|
|
|
return new BasicAuthenticationConsumer(usernameSupplier, passwordSupplier); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @see #basicAuthenticationConsumer |
|
|
|
|
*/ |
|
|
|
|
private static class BasicAuthenticationConsumer implements Consumer<HttpHeaders> { |
|
|
|
|
|
|
|
|
|
private final Supplier<String> usernameSupplier; |
|
|
|
|
|
|
|
|
|
private final Supplier<String> passwordSupplier; |
|
|
|
|
|
|
|
|
|
public BasicAuthenticationConsumer(Supplier<String> usernameSupplier, |
|
|
|
|
Supplier<String> passwordSupplier) { |
|
|
|
|
this.usernameSupplier = usernameSupplier; |
|
|
|
|
this.passwordSupplier = passwordSupplier; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void accept(HttpHeaders httpHeaders) { |
|
|
|
|
String username = this.usernameSupplier.get(); |
|
|
|
|
String password = this.passwordSupplier.get(); |
|
|
|
|
|
|
|
|
|
Assert.state(username != null, "Supplied username is null"); |
|
|
|
|
Assert.state(password != null, "Supplied password is null"); |
|
|
|
|
|
|
|
|
|
checkIllegalCharacters(username, password); |
|
|
|
|
|
|
|
|
|
String credentialsString = username + ":" + password; |
|
|
|
|
byte[] credentialBytes = credentialsString.getBytes(StandardCharsets.ISO_8859_1); |
|
|
|
|
byte[] encodedBytes = Base64.getEncoder().encode(credentialBytes); |
|
|
|
|
String encodedCredentials = new String(encodedBytes, StandardCharsets.ISO_8859_1); |
|
|
|
|
|
|
|
|
|
httpHeaders.set(HttpHeaders.AUTHORIZATION, "Basic " + encodedCredentials); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static void checkIllegalCharacters(String username, String password) { |
|
|
|
|
// Basic authentication only supports ISO 8859-1
|
|
|
|
|
CharsetEncoder encoder = StandardCharsets.ISO_8859_1.newEncoder(); |
|
|
|
|
if (!encoder.canEncode(username) || !encoder.canEncode(password)) { |
|
|
|
|
throw new IllegalArgumentException( |
|
|
|
|
"Username or password contains characters that cannot be encoded to ISO-8859-1"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|