Browse Source

Replace Streams with Loops

First version of replacing streams

fix wwwAuthenticate and codestyle

fix errors in implementation to pass tests

Fix review notes

Remove uneccessary final to align with cb

Short circuit way to authorize

Simplify error message, make code readably

Return error while duplicate key found

Delete check for duplicate, checkstyle issues

Return duplicate error

Fixes gh-7154
pull/7330/head
kostya05983 6 years ago committed by Josh Cummings
parent
commit
f6c650db47
No known key found for this signature in database
GPG Key ID: 49EF60DD7FF83443
  1. 22
      config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java
  2. 14
      core/src/main/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManager.java
  3. 26
      core/src/main/java/org/springframework/security/converter/RsaKeyConverters.java
  4. 8
      core/src/main/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsService.java
  5. 7
      core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java
  6. 13
      oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/DelegatingOAuth2AuthorizedClientProvider.java
  7. 14
      oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilder.java
  8. 6
      oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenValidator.java
  9. 23
      oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryClientRegistrationRepository.java
  10. 15
      oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryReactiveClientRegistrationRepository.java
  11. 10
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenValidatorTests.java
  12. 12
      oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/InMemoryClientRegistrationRepositoryTests.java
  13. 14
      oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToListStringConverter.java
  14. 11
      oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequest.java
  15. 29
      oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverter.java
  16. 25
      oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/DefaultOAuth2User.java
  17. 11
      oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/MacAlgorithm.java
  18. 12
      oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/SignatureAlgorithm.java
  19. 20
      oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverter.java
  20. 10
      oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java
  21. 10
      oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java
  22. 26
      oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationEntryPoint.java
  23. 27
      oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/access/BearerTokenAccessDeniedHandler.java
  24. 18
      oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/access/server/BearerTokenServerAccessDeniedHandler.java
  25. 21
      oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/BearerTokenServerAuthenticationEntryPoint.java
  26. 14
      web/src/main/java/org/springframework/security/web/header/writers/ClearSiteDataHeaderWriter.java
  27. 10
      web/src/main/java/org/springframework/security/web/server/authentication/DelegatingServerAuthenticationSuccessHandler.java
  28. 14
      web/src/main/java/org/springframework/security/web/server/authentication/logout/DelegatingServerLogoutHandler.java
  29. 12
      web/src/main/java/org/springframework/security/web/server/header/ClearSiteDataServerHttpHeadersWriter.java
  30. 11
      web/src/main/java/org/springframework/security/web/server/header/CompositeServerHttpHeadersWriter.java

22
config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java

@ -43,12 +43,11 @@ import org.springframework.security.crypto.factory.PasswordEncoderFactories; @@ -43,12 +43,11 @@ import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.Assert;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
/**
* Exports the authentication {@link Configuration}
@ -153,10 +152,7 @@ public class AuthenticationConfiguration { @@ -153,10 +152,7 @@ public class AuthenticationConfiguration {
}
String beanName;
if (beanNamesForType.length > 1) {
List<String> primaryBeanNames = Arrays.stream(beanNamesForType)
.filter(i -> applicationContext instanceof ConfigurableApplicationContext)
.filter(n -> ((ConfigurableApplicationContext) applicationContext).getBeanFactory().getBeanDefinition(n).isPrimary())
.collect(Collectors.toList());
List<String> primaryBeanNames = getPrimaryBeanNames(beanNamesForType);
Assert.isTrue(primaryBeanNames.size() != 0, () -> "Found " + beanNamesForType.length
+ " beans for type " + interfaceName + ", but none marked as primary");
@ -175,6 +171,20 @@ public class AuthenticationConfiguration { @@ -175,6 +171,20 @@ public class AuthenticationConfiguration {
return (T) proxyFactory.getObject();
}
private List<String> getPrimaryBeanNames(String[] beanNamesForType) {
List<String> list = new ArrayList<>();
if (!(applicationContext instanceof ConfigurableApplicationContext)) {
return Collections.emptyList();
}
for (String beanName : beanNamesForType) {
if (((ConfigurableApplicationContext) applicationContext).getBeanFactory()
.getBeanDefinition(beanName).isPrimary()) {
list.add(beanName);
}
}
return list;
}
private AuthenticationManager getAuthenticationManagerBean() {
return lazyBean(AuthenticationManager.class);
}

14
core/src/main/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManager.java

@ -22,7 +22,6 @@ import reactor.core.publisher.Mono; @@ -22,7 +22,6 @@ import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
/**
* A {@link ReactiveAuthorizationManager} that determines if the current user is
@ -109,9 +108,14 @@ public class AuthorityReactiveAuthorizationManager<T> implements ReactiveAuthori @@ -109,9 +108,14 @@ public class AuthorityReactiveAuthorizationManager<T> implements ReactiveAuthori
Assert.notNull(role, "role cannot be null");
}
return hasAnyAuthority(Stream.of(roles)
.map(r -> "ROLE_" + r)
.toArray(String[]::new)
);
return hasAnyAuthority(toNamedRolesArray(roles));
}
private static String[] toNamedRolesArray(String... roles) {
String[] result = new String[roles.length];
for (int i=0; i < roles.length; i++) {
result[i] = "ROLE_" + roles[i];
}
return result;
}
}

26
core/src/main/java/org/springframework/security/converter/RsaKeyConverters.java

@ -16,8 +16,8 @@ @@ -16,8 +16,8 @@
package org.springframework.security.converter;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
@ -25,8 +25,8 @@ import java.security.interfaces.RSAPrivateKey; @@ -25,8 +25,8 @@ import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.List;
import java.util.Base64;
import java.util.stream.Collectors;
import org.springframework.core.convert.converter.Converter;
@ -66,10 +66,13 @@ public class RsaKeyConverters { @@ -66,10 +66,13 @@ public class RsaKeyConverters {
Assert.isTrue(!lines.isEmpty() && lines.get(0).startsWith(PKCS8_PEM_HEADER),
"Key is not in PEM-encoded PKCS#8 format, " +
"please check that the header begins with -----" + PKCS8_PEM_HEADER + "-----");
String base64Encoded = lines.stream()
.filter(RsaKeyConverters::isNotPkcs8Wrapper)
.collect(Collectors.joining());
byte[] pkcs8 = Base64.getDecoder().decode(base64Encoded);
StringBuilder base64Encoded = new StringBuilder();
for (String line : lines) {
if (RsaKeyConverters.isNotPkcs8Wrapper(line)) {
base64Encoded.append(line);
}
}
byte[] pkcs8 = Base64.getDecoder().decode(base64Encoded.toString());
try {
return (RSAPrivateKey) keyFactory.generatePrivate(
@ -97,10 +100,13 @@ public class RsaKeyConverters { @@ -97,10 +100,13 @@ public class RsaKeyConverters {
Assert.isTrue(!lines.isEmpty() && lines.get(0).startsWith(X509_PEM_HEADER),
"Key is not in PEM-encoded X.509 format, " +
"please check that the header begins with -----" + X509_PEM_HEADER + "-----");
String base64Encoded = lines.stream()
.filter(RsaKeyConverters::isNotX509Wrapper)
.collect(Collectors.joining());
byte[] x509 = Base64.getDecoder().decode(base64Encoded);
StringBuilder base64Encoded = new StringBuilder();
for (String line : lines) {
if (RsaKeyConverters.isNotX509Wrapper(line)) {
base64Encoded.append(line);
}
}
byte[] x509 = Base64.getDecoder().decode(base64Encoded.toString());
try {
return (RSAPublicKey) keyFactory.generatePublic(

8
core/src/main/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsService.java

@ -19,8 +19,7 @@ package org.springframework.security.core.userdetails; @@ -19,8 +19,7 @@ package org.springframework.security.core.userdetails;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.util.Assert;
import reactor.core.publisher.Mono;
@ -56,7 +55,10 @@ public class MapReactiveUserDetailsService implements ReactiveUserDetailsService @@ -56,7 +55,10 @@ public class MapReactiveUserDetailsService implements ReactiveUserDetailsService
*/
public MapReactiveUserDetailsService(Collection<UserDetails> users) {
Assert.notEmpty(users, "users cannot be null or empty");
this.users = users.stream().collect(Collectors.toConcurrentMap( u -> getKey(u.getUsername()), Function.identity()));
this.users = new ConcurrentHashMap<>();
for (UserDetails user : users) {
this.users.put(getKey(user.getUsername()), user);
}
}
@Override

7
core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java

@ -46,6 +46,13 @@ public class MapReactiveUserDetailsServiceTests { @@ -46,6 +46,13 @@ public class MapReactiveUserDetailsServiceTests {
new MapReactiveUserDetailsService(users);
}
@Test
public void constructorCaseIntensiveKey() {
UserDetails userDetails = User.withUsername("USER").password("password").roles("USER").build();
MapReactiveUserDetailsService userDetailsService = new MapReactiveUserDetailsService(userDetails);
assertThat(userDetailsService.findByUsername("user").block()).isEqualTo(userDetails);
}
@Test
public void findByUsernameWhenFoundThenReturns() {
assertThat((users.findByUsername(USER_DETAILS.getUsername()).block())).isEqualTo(USER_DETAILS);

13
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/DelegatingOAuth2AuthorizedClientProvider.java

@ -22,7 +22,6 @@ import java.util.ArrayList; @@ -22,7 +22,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* An implementation of an {@link OAuth2AuthorizedClientProvider} that simply delegates
@ -64,10 +63,12 @@ public final class DelegatingOAuth2AuthorizedClientProvider implements OAuth2Aut @@ -64,10 +63,12 @@ public final class DelegatingOAuth2AuthorizedClientProvider implements OAuth2Aut
@Nullable
public OAuth2AuthorizedClient authorize(OAuth2AuthorizationContext context) {
Assert.notNull(context, "context cannot be null");
return this.authorizedClientProviders.stream()
.map(authorizedClientProvider -> authorizedClientProvider.authorize(context))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
for (OAuth2AuthorizedClientProvider authorizedClientProvider : authorizedClientProviders) {
OAuth2AuthorizedClient oauth2AuthorizedClient = authorizedClientProvider.authorize(context);
if (oauth2AuthorizedClient != null) {
return oauth2AuthorizedClient;
}
}
return null;
}
}

14
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilder.java

@ -23,11 +23,11 @@ import org.springframework.util.Assert; @@ -23,11 +23,11 @@ import org.springframework.util.Assert;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.List;
import java.util.LinkedHashMap;
import java.util.ArrayList;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* A builder that builds a {@link DelegatingOAuth2AuthorizedClientProvider} composed of
@ -286,10 +286,10 @@ public final class OAuth2AuthorizedClientProviderBuilder { @@ -286,10 +286,10 @@ public final class OAuth2AuthorizedClientProviderBuilder {
* @return the {@link DelegatingOAuth2AuthorizedClientProvider}
*/
public OAuth2AuthorizedClientProvider build() {
List<OAuth2AuthorizedClientProvider> authorizedClientProviders =
this.builders.values().stream()
.map(Builder::build)
.collect(Collectors.toList());
List<OAuth2AuthorizedClientProvider> authorizedClientProviders = new ArrayList<>();
for (Builder builder : this.builders.values()) {
authorizedClientProviders.add(builder.build());
}
return new DelegatingOAuth2AuthorizedClientProvider(authorizedClientProviders);
}

6
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenValidator.java

@ -32,7 +32,6 @@ import java.time.Instant; @@ -32,7 +32,6 @@ import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* An {@link OAuth2TokenValidator} responsible for
@ -137,11 +136,8 @@ public final class OidcIdTokenValidator implements OAuth2TokenValidator<Jwt> { @@ -137,11 +136,8 @@ public final class OidcIdTokenValidator implements OAuth2TokenValidator<Jwt> {
}
private static OAuth2Error invalidIdToken(Map<String, Object> invalidClaims) {
String claimsDetail = invalidClaims.entrySet().stream()
.map(it -> it.getKey() + " (" + it.getValue() + ")")
.collect(Collectors.joining(", "));
return new OAuth2Error("invalid_id_token",
"The ID Token contains invalid claims: " + claimsDetail,
"The ID Token contains invalid claims: " + invalidClaims,
"https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation");
}

23
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryClientRegistrationRepository.java

@ -22,12 +22,7 @@ import java.util.Collections; @@ -22,12 +22,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import java.util.stream.Collector;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
/**
* A {@link ClientRegistrationRepository} that stores {@link ClientRegistration}(s) in-memory.
@ -62,9 +57,19 @@ public final class InMemoryClientRegistrationRepository implements ClientRegistr @@ -62,9 +57,19 @@ public final class InMemoryClientRegistrationRepository implements ClientRegistr
private static Map<String, ClientRegistration> createRegistrationsMap(List<ClientRegistration> registrations) {
Assert.notEmpty(registrations, "registrations cannot be empty");
Collector<ClientRegistration, ?, ConcurrentMap<String, ClientRegistration>> collector =
toConcurrentMap(ClientRegistration::getRegistrationId, Function.identity());
return registrations.stream().collect(collectingAndThen(collector, Collections::unmodifiableMap));
return toUnmodifiableConcurrentMap(registrations);
}
private static Map<String, ClientRegistration> toUnmodifiableConcurrentMap(List<ClientRegistration> registrations) {
ConcurrentHashMap<String, ClientRegistration> result = new ConcurrentHashMap<>();
for (ClientRegistration registration : registrations) {
if (result.containsKey(registration.getRegistrationId())) {
throw new IllegalStateException(String.format("Duplicate key %s",
registration.getRegistrationId()));
}
result.put(registration.getRegistrationId(), registration);
}
return Collections.unmodifiableMap(result);
}
/**

15
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryReactiveClientRegistrationRepository.java

@ -19,8 +19,7 @@ import java.util.Iterator; @@ -19,8 +19,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.util.Assert;
@ -61,11 +60,9 @@ public final class InMemoryReactiveClientRegistrationRepository @@ -61,11 +60,9 @@ public final class InMemoryReactiveClientRegistrationRepository
*/
public InMemoryReactiveClientRegistrationRepository(List<ClientRegistration> registrations) {
Assert.notEmpty(registrations, "registrations cannot be null or empty");
this.clientIdToClientRegistration = registrations.stream()
.collect(Collectors.toConcurrentMap(ClientRegistration::getRegistrationId, Function.identity()));
this.clientIdToClientRegistration = toConcurrentMap(registrations);
}
@Override
public Mono<ClientRegistration> findByRegistrationId(String registrationId) {
return Mono.justOrEmpty(this.clientIdToClientRegistration.get(registrationId));
@ -80,4 +77,12 @@ public final class InMemoryReactiveClientRegistrationRepository @@ -80,4 +77,12 @@ public final class InMemoryReactiveClientRegistrationRepository
public Iterator<ClientRegistration> iterator() {
return this.clientIdToClientRegistration.values().iterator();
}
private ConcurrentHashMap<String, ClientRegistration> toConcurrentMap(List<ClientRegistration> registrations) {
ConcurrentHashMap<String, ClientRegistration> result = new ConcurrentHashMap<>();
for (ClientRegistration registration : registrations) {
result.put(registration.getRegistrationId(), registration);
}
return result;
}
}

10
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenValidatorTests.java

@ -229,6 +229,16 @@ public class OidcIdTokenValidatorTests { @@ -229,6 +229,16 @@ public class OidcIdTokenValidatorTests {
.allMatch(msg -> msg.contains(IdTokenClaimNames.EXP));
}
@Test
public void validateFormatError() {
this.claims.remove(IdTokenClaimNames.SUB);
this.claims.remove(IdTokenClaimNames.AUD);
assertThat(this.validateIdToken())
.hasSize(1)
.extracting(OAuth2Error::getDescription)
.allMatch(msg -> msg.equals("The ID Token contains invalid claims: {sub=null, aud=null}"));
}
private Collection<OAuth2Error> validateIdToken() {
Jwt idToken = new Jwt("token123", this.issuedAt, this.expiresAt, this.headers, this.claims);
OidcIdTokenValidator validator = new OidcIdTokenValidator(this.registration.build());

12
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/InMemoryClientRegistrationRepositoryTests.java

@ -50,12 +50,6 @@ public class InMemoryClientRegistrationRepositoryTests { @@ -50,12 +50,6 @@ public class InMemoryClientRegistrationRepositoryTests {
new InMemoryClientRegistrationRepository(registrations);
}
@Test(expected = IllegalStateException.class)
public void constructorListClientRegistrationWhenDuplicateIdThenIllegalArgumentException() {
List<ClientRegistration> registrations = Arrays.asList(this.registration, this.registration);
new InMemoryClientRegistrationRepository(registrations);
}
@Test(expected = IllegalArgumentException.class)
public void constructorMapClientRegistrationWhenNullThenIllegalArgumentException() {
new InMemoryClientRegistrationRepository((Map<String, ClientRegistration>) null);
@ -67,6 +61,12 @@ public class InMemoryClientRegistrationRepositoryTests { @@ -67,6 +61,12 @@ public class InMemoryClientRegistrationRepositoryTests {
assertThat(clients).isEmpty();
}
@Test(expected = IllegalStateException.class)
public void constructorListClientRegistrationWhenDuplicateIdThenIllegalArgumentException() {
List<ClientRegistration> registrations = Arrays.asList(this.registration, this.registration);
new InMemoryClientRegistrationRepository(registrations);
}
@Test
public void findByRegistrationIdWhenFoundThenFound() {
String id = this.registration.getRegistrationId();

14
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToListStringConverter.java

@ -23,9 +23,8 @@ import java.util.Collection; @@ -23,9 +23,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.ArrayList;
/**
* @author Joe Grandja
@ -64,10 +63,13 @@ final class ObjectToListStringConverter implements ConditionalGenericConverter { @@ -64,10 +63,13 @@ final class ObjectToListStringConverter implements ConditionalGenericConverter {
}
}
if (source instanceof Collection) {
return ((Collection<?>) source).stream()
.filter(Objects::nonNull)
.map(Objects::toString)
.collect(Collectors.toList());
Collection<String> results = new ArrayList<>();
for (Object object : ((Collection<?>) source)) {
if (object != null) {
results.add(object.toString());
}
}
return results;
}
return Collections.singletonList(source.toString());
}

11
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequest.java

@ -26,13 +26,11 @@ import org.springframework.web.util.UriComponentsBuilder; @@ -26,13 +26,11 @@ import org.springframework.web.util.UriComponentsBuilder;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* A representation of an OAuth 2.0 Authorization Request
@ -275,8 +273,7 @@ public final class OAuth2AuthorizationRequest implements Serializable { @@ -275,8 +273,7 @@ public final class OAuth2AuthorizationRequest implements Serializable {
*/
public Builder scope(String... scope) {
if (scope != null && scope.length > 0) {
return this.scopes(Arrays.stream(scope).collect(
Collectors.toCollection(LinkedHashSet::new)));
return this.scopes(toLinkedHashSet(scope));
}
return this;
}
@ -401,5 +398,11 @@ public final class OAuth2AuthorizationRequest implements Serializable { @@ -401,5 +398,11 @@ public final class OAuth2AuthorizationRequest implements Serializable {
.build()
.toUriString();
}
private LinkedHashSet<String> toLinkedHashSet(String... scope) {
LinkedHashSet<String> result = new LinkedHashSet<>();
Collections.addAll(result, scope);
return result;
}
}
}

29
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverter.java

@ -37,14 +37,13 @@ import java.nio.charset.Charset; @@ -37,14 +37,13 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.HashMap;
/**
* A {@link HttpMessageConverter} for an {@link OAuth2AccessTokenResponse OAuth 2.0 Access Token Response}.
@ -132,12 +131,13 @@ public class OAuth2AccessTokenResponseHttpMessageConverter extends AbstractHttpM @@ -132,12 +131,13 @@ public class OAuth2AccessTokenResponseHttpMessageConverter extends AbstractHttpM
* OAuth 2.0 Access Token Response parameters to an {@link OAuth2AccessTokenResponse}.
*/
private static class OAuth2AccessTokenResponseConverter implements Converter<Map<String, String>, OAuth2AccessTokenResponse> {
private static final Set<String> TOKEN_RESPONSE_PARAMETER_NAMES = Stream.of(
private static final Set<String> TOKEN_RESPONSE_PARAMETER_NAMES = new HashSet<>(Arrays.asList(
OAuth2ParameterNames.ACCESS_TOKEN,
OAuth2ParameterNames.TOKEN_TYPE,
OAuth2ParameterNames.EXPIRES_IN,
OAuth2ParameterNames.REFRESH_TOKEN,
OAuth2ParameterNames.SCOPE).collect(Collectors.toSet());
OAuth2ParameterNames.SCOPE
));
@Override
public OAuth2AccessTokenResponse convert(Map<String, String> tokenResponseParameters) {
@ -159,15 +159,17 @@ public class OAuth2AccessTokenResponseHttpMessageConverter extends AbstractHttpM @@ -159,15 +159,17 @@ public class OAuth2AccessTokenResponseHttpMessageConverter extends AbstractHttpM
Set<String> scopes = Collections.emptySet();
if (tokenResponseParameters.containsKey(OAuth2ParameterNames.SCOPE)) {
String scope = tokenResponseParameters.get(OAuth2ParameterNames.SCOPE);
scopes = Arrays.stream(StringUtils.delimitedListToStringArray(scope, " ")).collect(Collectors.toSet());
scopes = new HashSet<>(Arrays.asList(StringUtils.delimitedListToStringArray(scope, " ")));
}
String refreshToken = tokenResponseParameters.get(OAuth2ParameterNames.REFRESH_TOKEN);
Map<String, Object> additionalParameters = new LinkedHashMap<>();
tokenResponseParameters.entrySet().stream()
.filter(e -> !TOKEN_RESPONSE_PARAMETER_NAMES.contains(e.getKey()))
.forEach(e -> additionalParameters.put(e.getKey(), e.getValue()));
for (Map.Entry<String, String> entry : tokenResponseParameters.entrySet()) {
if (!TOKEN_RESPONSE_PARAMETER_NAMES.contains(entry.getKey())) {
additionalParameters.put(entry.getKey(), entry.getValue());
}
}
return OAuth2AccessTokenResponse.withToken(accessToken)
.tokenType(accessTokenType)
@ -205,8 +207,9 @@ public class OAuth2AccessTokenResponseHttpMessageConverter extends AbstractHttpM @@ -205,8 +207,9 @@ public class OAuth2AccessTokenResponseHttpMessageConverter extends AbstractHttpM
parameters.put(OAuth2ParameterNames.REFRESH_TOKEN, tokenResponse.getRefreshToken().getTokenValue());
}
if (!CollectionUtils.isEmpty(tokenResponse.getAdditionalParameters())) {
tokenResponse.getAdditionalParameters().entrySet().stream()
.forEach(e -> parameters.put(e.getKey(), e.getValue().toString()));
for (Map.Entry<String, Object> entry : tokenResponse.getAdditionalParameters().entrySet()) {
parameters.put(entry.getKey(), entry.getValue().toString());
}
}
return parameters;

25
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/DefaultOAuth2User.java

@ -20,16 +20,15 @@ import org.springframework.security.core.SpringSecurityCoreVersion; @@ -20,16 +20,15 @@ import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.util.Assert;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.Collections;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.TreeSet;
import java.util.stream.Collectors;
import java.util.SortedSet;
import java.util.Comparator;
import java.util.LinkedHashSet;
/**
* The default implementation of an {@link OAuth2User}.
@ -43,8 +42,8 @@ import java.util.stream.Collectors; @@ -43,8 +42,8 @@ import java.util.stream.Collectors;
* and returning it from {@link #getName()}.
*
* @author Joe Grandja
* @since 5.0
* @see OAuth2User
* @since 5.0
*/
public class DefaultOAuth2User implements OAuth2User, Serializable {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
@ -55,8 +54,8 @@ public class DefaultOAuth2User implements OAuth2User, Serializable { @@ -55,8 +54,8 @@ public class DefaultOAuth2User implements OAuth2User, Serializable {
/**
* Constructs a {@code DefaultOAuth2User} using the provided parameters.
*
* @param authorities the authorities granted to the user
* @param attributes the attributes about the user
* @param authorities the authorities granted to the user
* @param attributes the attributes about the user
* @param nameAttributeKey the key used to access the user's &quot;name&quot; from {@link #getAttributes()}
*/
public DefaultOAuth2User(Collection<? extends GrantedAuthority> authorities, Map<String, Object> attributes, String nameAttributeKey) {
@ -88,7 +87,7 @@ public class DefaultOAuth2User implements OAuth2User, Serializable { @@ -88,7 +87,7 @@ public class DefaultOAuth2User implements OAuth2User, Serializable {
private Set<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) {
SortedSet<GrantedAuthority> sortedAuthorities =
new TreeSet<>(Comparator.comparing(GrantedAuthority::getAuthority));
new TreeSet<>(Comparator.comparing(GrantedAuthority::getAuthority));
sortedAuthorities.addAll(authorities);
return sortedAuthorities;
}
@ -127,9 +126,9 @@ public class DefaultOAuth2User implements OAuth2User, Serializable { @@ -127,9 +126,9 @@ public class DefaultOAuth2User implements OAuth2User, Serializable {
sb.append("Name: [");
sb.append(this.getName());
sb.append("], Granted Authorities: [");
sb.append(this.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(", ")));
sb.append(getAuthorities());
sb.append("], User Attributes: [");
sb.append(this.getAttributes().entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(", ")));
sb.append(getAttributes());
sb.append("]");
return sb.toString();
}

11
oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/MacAlgorithm.java

@ -15,7 +15,6 @@ @@ -15,7 +15,6 @@
*/
package org.springframework.security.oauth2.jose.jws;
import java.util.stream.Stream;
/**
* An enumeration of the cryptographic algorithms defined by the JSON Web Algorithms (JWA) specification
@ -59,10 +58,12 @@ public enum MacAlgorithm implements JwsAlgorithm { @@ -59,10 +58,12 @@ public enum MacAlgorithm implements JwsAlgorithm {
* @return the resolved {@code MacAlgorithm}, or {@code null} if not found
*/
public static MacAlgorithm from(String name) {
return Stream.of(values())
.filter(algorithm -> algorithm.getName().equals(name))
.findFirst()
.orElse(null);
for (MacAlgorithm algorithm : values()) {
if (algorithm.getName().equals(name)) {
return algorithm;
}
}
return null;
}
/**

12
oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/SignatureAlgorithm.java

@ -15,8 +15,6 @@ @@ -15,8 +15,6 @@
*/
package org.springframework.security.oauth2.jose.jws;
import java.util.stream.Stream;
/**
* An enumeration of the cryptographic algorithms defined by the JSON Web Algorithms (JWA) specification
* and used by JSON Web Signature (JWS) to digitally sign the contents of the JWS Protected Header and JWS Payload.
@ -89,10 +87,12 @@ public enum SignatureAlgorithm implements JwsAlgorithm { @@ -89,10 +87,12 @@ public enum SignatureAlgorithm implements JwsAlgorithm {
* @return the resolved {@code SignatureAlgorithm}, or {@code null} if not found
*/
public static SignatureAlgorithm from(String name) {
return Stream.of(values())
.filter(algorithm -> algorithm.getName().equals(name))
.findFirst()
.orElse(null);
for (SignatureAlgorithm value : values()) {
if (value.getName().equals(name)) {
return value;
}
}
return null;
}
/**

20
oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverter.java

@ -29,7 +29,6 @@ import java.time.Instant; @@ -29,7 +29,6 @@ import java.time.Instant;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Converts a JWT claim set, claim by claim. Can be configured with custom converters
@ -161,17 +160,22 @@ public final class MappedJwtClaimSetConverter implements Converter<Map<String, O @@ -161,17 +160,22 @@ public final class MappedJwtClaimSetConverter implements Converter<Map<String, O
}
private Map<String, Object> removeClaims(Map<String, Object> claims) {
return claims.entrySet().stream()
.filter(e -> e.getValue() != null)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Map<String, Object> result = new HashMap<>();
for (Map.Entry<String, Object> entry : claims.entrySet()) {
if (entry.getValue() != null) {
result.put(entry.getKey(), entry.getValue());
}
}
return result;
}
private Map<String, Object> addClaims(Map<String, Object> claims) {
Map<String, Object> result = new HashMap<>(claims);
this.claimTypeConverters.entrySet().stream()
.filter(e -> !claims.containsKey(e.getKey()))
.filter(e -> e.getValue().convert(null) != null)
.forEach(e -> result.put(e.getKey(), e.getValue().convert(null)));
for (Map.Entry<String, Converter<Object, ?>> entry : claimTypeConverters.entrySet()) {
if (!claims.containsKey(entry.getKey()) && entry.getValue().convert(null) != null) {
result.put(entry.getKey(), entry.getValue().convert(null));
}
}
return result;
}
}

10
oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java

@ -22,7 +22,7 @@ import java.time.Instant; @@ -22,7 +22,7 @@ import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.ArrayList;
import com.nimbusds.oauth2.sdk.TokenIntrospectionResponse;
import com.nimbusds.oauth2.sdk.TokenIntrospectionSuccessResponse;
@ -192,9 +192,11 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector { @@ -192,9 +192,11 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
private Map<String, Object> convertClaimsSet(TokenIntrospectionSuccessResponse response) {
Map<String, Object> claims = response.toJSONObject();
if (response.getAudience() != null) {
List<String> audience = response.getAudience().stream()
.map(Audience::getValue).collect(Collectors.toList());
claims.put(AUDIENCE, Collections.unmodifiableList(audience));
List<String> audiences = new ArrayList<>();
for (Audience audience : response.getAudience()) {
audiences.add(audience.getValue());
}
claims.put(AUDIENCE, Collections.unmodifiableList(audiences));
}
if (response.getClientID() != null) {
claims.put(CLIENT_ID, response.getClientID().getValue());

10
oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java

@ -22,7 +22,7 @@ import java.time.Instant; @@ -22,7 +22,7 @@ import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.ArrayList;
import com.nimbusds.oauth2.sdk.TokenIntrospectionResponse;
import com.nimbusds.oauth2.sdk.TokenIntrospectionSuccessResponse;
@ -153,9 +153,11 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke @@ -153,9 +153,11 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
private Map<String, Object> convertClaimsSet(TokenIntrospectionSuccessResponse response) {
Map<String, Object> claims = response.toJSONObject();
if (response.getAudience() != null) {
List<String> audience = response.getAudience().stream()
.map(Audience::getValue).collect(Collectors.toList());
claims.put(AUDIENCE, Collections.unmodifiableList(audience));
List<String> audiences = new ArrayList<>();
for (Audience audience : response.getAudience()) {
audiences.add(audience.getValue());
}
claims.put(AUDIENCE, Collections.unmodifiableList(audiences));
}
if (response.getClientID() != null) {
claims.put(CLIENT_ID, response.getClientID().getValue());

26
oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationEntryPoint.java

@ -19,7 +19,6 @@ package org.springframework.security.oauth2.server.resource.web; @@ -19,7 +19,6 @@ package org.springframework.security.oauth2.server.resource.web;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -41,10 +40,10 @@ import org.springframework.util.StringUtils; @@ -41,10 +40,10 @@ import org.springframework.util.StringUtils;
* {@code WWW-Authenticate} HTTP header.
*
* @author Vedran Pavic
* @since 5.1
* @see BearerTokenError
* @see <a href="https://tools.ietf.org/html/rfc6750#section-3" target="_blank">RFC 6750 Section 3: The WWW-Authenticate
* Response Header Field</a>
* @since 5.1
*/
public final class BearerTokenAuthenticationEntryPoint implements AuthenticationEntryPoint {
@ -54,8 +53,8 @@ public final class BearerTokenAuthenticationEntryPoint implements Authentication @@ -54,8 +53,8 @@ public final class BearerTokenAuthenticationEntryPoint implements Authentication
* Collect error details from the provided parameters and format according to
* RFC 6750, specifically {@code error}, {@code error_description}, {@code error_uri}, and {@code scope}.
*
* @param request that resulted in an <code>AuthenticationException</code>
* @param response so that the user agent can begin authentication
* @param request that resulted in an <code>AuthenticationException</code>
* @param response so that the user agent can begin authentication
* @param authException that caused the invocation
*/
@Override
@ -112,13 +111,22 @@ public final class BearerTokenAuthenticationEntryPoint implements Authentication @@ -112,13 +111,22 @@ public final class BearerTokenAuthenticationEntryPoint implements Authentication
}
private static String computeWWWAuthenticateHeaderValue(Map<String, String> parameters) {
String wwwAuthenticate = "Bearer";
StringBuilder wwwAuthenticate = new StringBuilder();
wwwAuthenticate.append("Bearer");
if (!parameters.isEmpty()) {
wwwAuthenticate += parameters.entrySet().stream()
.map(attribute -> attribute.getKey() + "=\"" + attribute.getValue() + "\"")
.collect(Collectors.joining(", ", " ", ""));
wwwAuthenticate.append(" ");
int i = 0;
for (Map.Entry<String, String> entry : parameters.entrySet()) {
wwwAuthenticate.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
if (i != parameters.size() - 1) {
wwwAuthenticate.append(", ");
}
i++;
}
}
return wwwAuthenticate;
return wwwAuthenticate.toString();
}
}

27
oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/access/BearerTokenAccessDeniedHandler.java

@ -30,12 +30,11 @@ import javax.servlet.http.HttpServletResponse; @@ -30,12 +30,11 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Translates any {@link AccessDeniedException} into an HTTP response in accordance with
* <a href="https://tools.ietf.org/html/rfc6750#section-3" target="_blank">RFC 6750 Section 3: The WWW-Authenticate</a>.
*
* <p>
* So long as the class can prove that the request has a valid OAuth 2.0 {@link Authentication}, then will return an
* <a href="https://tools.ietf.org/html/rfc6750#section-3.1" target="_blank">insufficient scope error</a>; otherwise,
* it will simply indicate the scheme (Bearer) and any configured realm.
@ -51,10 +50,9 @@ public final class BearerTokenAccessDeniedHandler implements AccessDeniedHandler @@ -51,10 +50,9 @@ public final class BearerTokenAccessDeniedHandler implements AccessDeniedHandler
* Collect error details from the provided parameters and format according to
* RFC 6750, specifically {@code error}, {@code error_description}, {@code error_uri}, and {@code scope}.
*
* @param request that resulted in an <code>AccessDeniedException</code>
* @param response so that the user agent can be advised of the failure
* @param request that resulted in an <code>AccessDeniedException</code>
* @param response so that the user agent can be advised of the failure
* @param accessDeniedException that caused the invocation
*
*/
@Override
public void handle(
@ -90,13 +88,22 @@ public final class BearerTokenAccessDeniedHandler implements AccessDeniedHandler @@ -90,13 +88,22 @@ public final class BearerTokenAccessDeniedHandler implements AccessDeniedHandler
}
private static String computeWWWAuthenticateHeaderValue(Map<String, String> parameters) {
String wwwAuthenticate = "Bearer";
StringBuilder wwwAuthenticate = new StringBuilder();
wwwAuthenticate.append("Bearer");
if (!parameters.isEmpty()) {
wwwAuthenticate += parameters.entrySet().stream()
.map(attribute -> attribute.getKey() + "=\"" + attribute.getValue() + "\"")
.collect(Collectors.joining(", ", " ", ""));
wwwAuthenticate.append(" ");
int i = 0;
for (Map.Entry<String, String> entry : parameters.entrySet()) {
wwwAuthenticate.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
if (i != parameters.size() - 1) {
wwwAuthenticate.append(", ");
}
i++;
}
}
return wwwAuthenticate;
return wwwAuthenticate.toString();
}
}

18
oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/access/server/BearerTokenServerAccessDeniedHandler.java

@ -30,7 +30,6 @@ import java.util.Arrays; @@ -30,7 +30,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Translates any {@link AccessDeniedException} into an HTTP response in accordance with
@ -91,13 +90,20 @@ public class BearerTokenServerAccessDeniedHandler implements ServerAccessDeniedH @@ -91,13 +90,20 @@ public class BearerTokenServerAccessDeniedHandler implements ServerAccessDeniedH
}
private static String computeWWWAuthenticateHeaderValue(Map<String, String> parameters) {
String wwwAuthenticate = "Bearer";
StringBuilder wwwAuthenticate = new StringBuilder();
wwwAuthenticate.append("Bearer");
if (!parameters.isEmpty()) {
wwwAuthenticate += parameters.entrySet().stream()
.map(attribute -> attribute.getKey() + "=\"" + attribute.getValue() + "\"")
.collect(Collectors.joining(", ", " ", ""));
wwwAuthenticate.append(" ");
int i = 0;
for (Map.Entry<String, String> entry : parameters.entrySet()) {
wwwAuthenticate.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
if (i != parameters.size() - 1) {
wwwAuthenticate.append(", ");
}
i++;
}
}
return wwwAuthenticate;
return wwwAuthenticate.toString();
}
}

21
oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/BearerTokenServerAuthenticationEntryPoint.java

@ -32,7 +32,6 @@ import reactor.core.publisher.Mono; @@ -32,7 +32,6 @@ import reactor.core.publisher.Mono;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
* An {@link AuthenticationEntryPoint} implementation used to commence authentication of protected resource requests
@ -42,10 +41,10 @@ import java.util.stream.Collectors; @@ -42,10 +41,10 @@ import java.util.stream.Collectors;
* {@code WWW-Authenticate} HTTP header.
*
* @author Rob Winch
* @since 5.1
* @see BearerTokenError
* @see <a href="https://tools.ietf.org/html/rfc6750#section-3" target="_blank">RFC 6750 Section 3: The WWW-Authenticate
* Response Header Field</a>
* @since 5.1
*/
public final class BearerTokenServerAuthenticationEntryPoint implements
ServerAuthenticationEntryPoint {
@ -111,13 +110,21 @@ public final class BearerTokenServerAuthenticationEntryPoint implements @@ -111,13 +110,21 @@ public final class BearerTokenServerAuthenticationEntryPoint implements
}
private static String computeWWWAuthenticateHeaderValue(Map<String, String> parameters) {
String wwwAuthenticate = "Bearer";
StringBuilder wwwAuthenticate = new StringBuilder();
wwwAuthenticate.append("Bearer");
if (!parameters.isEmpty()) {
wwwAuthenticate += parameters.entrySet().stream()
.map(attribute -> attribute.getKey() + "=\"" + attribute.getValue() + "\"")
.collect(Collectors.joining(", ", " ", ""));
wwwAuthenticate.append(" ");
int i = 0;
for (Map.Entry<String, String> entry : parameters.entrySet()) {
wwwAuthenticate.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
if (i != parameters.size() - 1) {
wwwAuthenticate.append(", ");
}
i++;
}
}
return wwwAuthenticate;
return wwwAuthenticate.toString();
}
}

14
web/src/main/java/org/springframework/security/web/header/writers/ClearSiteDataHeaderWriter.java

@ -16,9 +16,6 @@ @@ -16,9 +16,6 @@
package org.springframework.security.web.header.writers;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -69,7 +66,7 @@ public final class ClearSiteDataHeaderWriter implements HeaderWriter { @@ -69,7 +66,7 @@ public final class ClearSiteDataHeaderWriter implements HeaderWriter {
public ClearSiteDataHeaderWriter(String ...sources) {
Assert.notEmpty(sources, "sources cannot be empty or null");
this.requestMatcher = new SecureRequestMatcher();
this.headerValue = Stream.of(sources).map(this::quote).collect(Collectors.joining(", "));
this.headerValue = joinQuotes(sources);
}
@Override
@ -84,6 +81,15 @@ public final class ClearSiteDataHeaderWriter implements HeaderWriter { @@ -84,6 +81,15 @@ public final class ClearSiteDataHeaderWriter implements HeaderWriter {
}
}
private String joinQuotes(String ...sources) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < sources.length-1; i++) {
sb.append(quote(sources[i])).append(", ");
}
sb.append(quote(sources[sources.length-1]));
return sb.toString();
}
private static final class SecureRequestMatcher implements RequestMatcher {
public boolean matches(HttpServletRequest request) {
return request.isSecure();

10
web/src/main/java/org/springframework/security/web/server/authentication/DelegatingServerAuthenticationSuccessHandler.java

@ -23,8 +23,7 @@ import reactor.core.publisher.Mono; @@ -23,8 +23,7 @@ import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.ArrayList;
/**
* Delegates to a collection of {@link ServerAuthenticationSuccessHandler} implementations.
@ -43,7 +42,10 @@ public class DelegatingServerAuthenticationSuccessHandler implements ServerAuthe @@ -43,7 +42,10 @@ public class DelegatingServerAuthenticationSuccessHandler implements ServerAuthe
@Override
public Mono<Void> onAuthenticationSuccess(WebFilterExchange exchange,
Authentication authentication) {
Stream<Mono<Void>> results = this.delegates.stream().map(delegate -> delegate.onAuthenticationSuccess(exchange, authentication));
return Mono.when(results.collect(Collectors.toList()));
List<Mono<Void>> results = new ArrayList<>();
for (ServerAuthenticationSuccessHandler delegate : delegates) {
results.add(delegate.onAuthenticationSuccess(exchange, authentication));
}
return Mono.when(results);
}
}

14
web/src/main/java/org/springframework/security/web/server/authentication/logout/DelegatingServerLogoutHandler.java

@ -20,8 +20,6 @@ import java.util.ArrayList; @@ -20,8 +20,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import reactor.core.publisher.Mono;
@ -50,10 +48,12 @@ public class DelegatingServerLogoutHandler implements ServerLogoutHandler { @@ -50,10 +48,12 @@ public class DelegatingServerLogoutHandler implements ServerLogoutHandler {
@Override
public Mono<Void> logout(WebFilterExchange exchange, Authentication authentication) {
return Mono.when(this.delegates.stream()
.filter(Objects::nonNull)
.map(delegate -> delegate.logout(exchange, authentication))
.collect(Collectors.toList())
);
List<Mono<Void>> results = new ArrayList<>();
for (ServerLogoutHandler delegate : delegates) {
if (delegate != null) {
results.add(delegate.logout(exchange, authentication));
}
}
return Mono.when(results);
}
}

12
web/src/main/java/org/springframework/security/web/server/header/ClearSiteDataServerHttpHeadersWriter.java

@ -20,9 +20,6 @@ import org.springframework.web.server.ServerWebExchange; @@ -20,9 +20,6 @@ import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* <p>Writes the {@code Clear-Site-Data} response header when the request is secure.</p>
*
@ -81,9 +78,12 @@ public final class ClearSiteDataServerHttpHeadersWriter implements ServerHttpHea @@ -81,9 +78,12 @@ public final class ClearSiteDataServerHttpHeadersWriter implements ServerHttpHea
}
private String transformToHeaderValue(Directive... directives) {
return Stream.of(directives)
.map(Directive::getHeaderValue)
.collect(Collectors.joining(", "));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < directives.length - 1; i++) {
sb.append(directives[i].headerValue).append(", ");
}
sb.append(directives[directives.length - 1].headerValue);
return sb.toString();
}
private boolean isSecure(ServerWebExchange exchange) {

11
web/src/main/java/org/springframework/security/web/server/header/CompositeServerHttpHeadersWriter.java

@ -17,8 +17,7 @@ package org.springframework.security.web.server.header; @@ -17,8 +17,7 @@ package org.springframework.security.web.server.header;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.ArrayList;
import org.springframework.web.server.ServerWebExchange;
@ -43,8 +42,10 @@ public class CompositeServerHttpHeadersWriter implements ServerHttpHeadersWriter @@ -43,8 +42,10 @@ public class CompositeServerHttpHeadersWriter implements ServerHttpHeadersWriter
@Override
public Mono<Void> writeHttpHeaders(ServerWebExchange exchange) {
Stream<Mono<Void>> results = writers.stream().map( writer -> writer.writeHttpHeaders(exchange));
return Mono.when(results.collect(Collectors.toList()));
List<Mono<Void>> results = new ArrayList<>();
for (ServerHttpHeadersWriter writer : writers) {
results.add(writer.writeHttpHeaders(exchange));
}
return Mono.when(results);
}
}

Loading…
Cancel
Save