Move Authority Propagation Into Filters
Given that the filters are the level at which the SecurityContextHolder is consulted, this commit moves the operation that ProviderManager was doing into each authentication filter. Issue gh-17862
This commit is contained in:
+6
@@ -248,6 +248,12 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
// return immediately as subclass has indicated that it hasn't completed
|
||||
return;
|
||||
}
|
||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (current != null && current.isAuthenticated()) {
|
||||
authenticationResult = authenticationResult.toBuilder()
|
||||
.authorities((a) -> a.addAll(current.getAuthorities()))
|
||||
.build();
|
||||
}
|
||||
this.sessionStrategy.onAuthentication(authenticationResult, request, response);
|
||||
// Authentication success
|
||||
if (this.continueChainBeforeSuccessfulAuthentication) {
|
||||
|
||||
+6
@@ -184,6 +184,12 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (current != null && current.isAuthenticated()) {
|
||||
authenticationResult = authenticationResult.toBuilder()
|
||||
.authorities((a) -> a.addAll(current.getAuthorities()))
|
||||
.build();
|
||||
}
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
request.changeSessionId();
|
||||
|
||||
+6
@@ -204,6 +204,12 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
principal, credentials);
|
||||
authenticationRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
|
||||
Authentication authenticationResult = this.authenticationManager.authenticate(authenticationRequest);
|
||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (current != null && current.isAuthenticated()) {
|
||||
authenticationResult = authenticationResult.toBuilder()
|
||||
.authorities((a) -> a.addAll(current.getAuthorities()))
|
||||
.build();
|
||||
}
|
||||
successfulAuthentication(request, response, authenticationResult);
|
||||
}
|
||||
catch (AuthenticationException ex) {
|
||||
|
||||
+4
@@ -186,6 +186,10 @@ public class BasicAuthenticationFilter extends OncePerRequestFilter {
|
||||
this.logger.trace(LogMessage.format("Found username '%s' in Basic Authorization header", username));
|
||||
if (authenticationIsRequired(username)) {
|
||||
Authentication authResult = this.authenticationManager.authenticate(authRequest);
|
||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (current != null && current.isAuthenticated()) {
|
||||
authResult = authResult.toBuilder().authorities((a) -> a.addAll(current.getAuthorities())).build();
|
||||
}
|
||||
SecurityContext context = this.securityContextHolderStrategy.createEmptyContext();
|
||||
context.setAuthentication(authResult);
|
||||
this.securityContextHolderStrategy.setContext(context);
|
||||
|
||||
+14
@@ -122,12 +122,26 @@ public class AuthenticationWebFilter implements WebFilter {
|
||||
.flatMap((authenticationManager) -> authenticationManager.authenticate(token))
|
||||
.switchIfEmpty(Mono
|
||||
.defer(() -> Mono.error(new IllegalStateException("No provider found for " + token.getClass()))))
|
||||
.flatMap(this::applyCurrentAuthenication)
|
||||
.flatMap(
|
||||
(authentication) -> onAuthenticationSuccess(authentication, new WebFilterExchange(exchange, chain)))
|
||||
.doOnError(AuthenticationException.class,
|
||||
(ex) -> logger.debug(LogMessage.format("Authentication failed: %s", ex.getMessage()), ex));
|
||||
}
|
||||
|
||||
private Mono<Authentication> applyCurrentAuthenication(Authentication result) {
|
||||
return ReactiveSecurityContextHolder.getContext().map((context) -> {
|
||||
Authentication current = context.getAuthentication();
|
||||
if (current == null) {
|
||||
return result;
|
||||
}
|
||||
if (!current.isAuthenticated()) {
|
||||
return result;
|
||||
}
|
||||
return result.toBuilder().authorities((a) -> a.addAll(current.getAuthorities())).build();
|
||||
}).switchIfEmpty(Mono.just(result));
|
||||
}
|
||||
|
||||
protected Mono<Void> onAuthenticationSuccess(Authentication authentication, WebFilterExchange webFilterExchange) {
|
||||
ServerWebExchange exchange = webFilterExchange.getExchange();
|
||||
SecurityContextImpl securityContext = new SecurityContextImpl();
|
||||
|
||||
+1
@@ -144,6 +144,7 @@ public class AuthenticationFilterTests {
|
||||
this.authenticationConverter);
|
||||
SecurityContextHolderStrategy strategy = mock(SecurityContextHolderStrategy.class);
|
||||
given(strategy.createEmptyContext()).willReturn(new SecurityContextImpl());
|
||||
given(strategy.getContext()).willReturn(new SecurityContextImpl());
|
||||
filter.setSecurityContextHolderStrategy(strategy);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Reference in New Issue
Block a user