Polish SecurityContextHolderStrategy for Defaults

gh-11060
This commit is contained in:
Josh Cummings 2022-06-21 16:43:41 -06:00
parent c29b91cec7
commit a7b58c2299
No known key found for this signature in database
GPG Key ID: A306A51F43B8E5A5
6 changed files with 86 additions and 11 deletions

View File

@ -26,6 +26,7 @@ import org.springframework.core.log.LogMessage;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.util.Assert;
/**
@ -45,6 +46,9 @@ public class SecurityContextLogoutHandler implements LogoutHandler {
protected final Log logger = LogFactory.getLog(this.getClass());
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private boolean invalidateHttpSession = true;
private boolean clearAuthentication = true;
@ -67,8 +71,8 @@ public class SecurityContextLogoutHandler implements LogoutHandler {
}
}
}
SecurityContext context = SecurityContextHolder.getContext();
SecurityContextHolder.clearContext();
SecurityContext context = this.securityContextHolderStrategy.getContext();
this.securityContextHolderStrategy.clearContext();
if (this.clearAuthentication) {
context.setAuthentication(null);
}
@ -78,6 +82,17 @@ public class SecurityContextLogoutHandler implements LogoutHandler {
return this.invalidateHttpSession;
}
/**
* Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
* the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.
*
* @since 5.8
*/
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
/**
* Causes the {@link HttpSession} to be invalidated when this {@link LogoutHandler} is
* invoked. Defaults to true.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2022 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.
@ -28,6 +28,7 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.security.core.annotation.CurrentSecurityContext;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@ -75,6 +76,9 @@ import org.springframework.web.method.support.ModelAndViewContainer;
*/
public final class CurrentSecurityContextArgumentResolver implements HandlerMethodArgumentResolver {
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private ExpressionParser parser = new SpelExpressionParser();
private BeanResolver beanResolver;
@ -87,7 +91,7 @@ public final class CurrentSecurityContextArgumentResolver implements HandlerMeth
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
SecurityContext securityContext = SecurityContextHolder.getContext();
SecurityContext securityContext = this.securityContextHolderStrategy.getContext();
if (securityContext == null) {
return null;
}
@ -113,6 +117,17 @@ public final class CurrentSecurityContextArgumentResolver implements HandlerMeth
return securityContextResult;
}
/**
* Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
* the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.
*
* @since 5.8
*/
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
/**
* Set the {@link BeanResolver} to be used on the expressions
* @param beanResolver the {@link BeanResolver} to use

View File

@ -41,6 +41,7 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.logout.LogoutHandler;
@ -76,6 +77,9 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
private Log logger = LogFactory.getLog(getClass());
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private final String rolePrefix;
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
@ -161,9 +165,17 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
this.trustResolver = trustResolver;
}
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
@Override
public HttpServletRequest create(HttpServletRequest request, HttpServletResponse response) {
return new Servlet3SecurityContextHolderAwareRequestWrapper(request, this.rolePrefix, response);
Servlet3SecurityContextHolderAwareRequestWrapper wrapper = new Servlet3SecurityContextHolderAwareRequestWrapper(
request, this.rolePrefix, response);
wrapper.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
return wrapper;
}
private class Servlet3SecurityContextHolderAwareRequestWrapper extends SecurityContextHolderAwareRequestWrapper {
@ -228,9 +240,10 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
return;
}
Authentication authentication = getAuthentication(authManager, username, password);
SecurityContext context = SecurityContextHolder.createEmptyContext();
SecurityContext context = HttpServlet3RequestFactory.this.securityContextHolderStrategy
.createEmptyContext();
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
HttpServlet3RequestFactory.this.securityContextHolderStrategy.setContext(context);
}
private Authentication getAuthentication(AuthenticationManager authManager, String username, String password)
@ -243,7 +256,7 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
return authManager.authenticate(authentication);
}
catch (AuthenticationException ex) {
SecurityContextHolder.clearContext();
HttpServlet3RequestFactory.this.securityContextHolderStrategy.clearContext();
throw new ServletException(ex.getMessage(), ex);
}
}
@ -257,7 +270,8 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
super.logout();
return;
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Authentication authentication = HttpServlet3RequestFactory.this.securityContextHolderStrategy.getContext()
.getAuthentication();
for (LogoutHandler handler : handlers) {
handler.logout(this, this.response, authentication);
}

View File

@ -32,6 +32,7 @@ import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.util.Assert;
@ -68,6 +69,9 @@ import org.springframework.web.filter.GenericFilterBean;
*/
public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private String rolePrefix = "ROLE_";
private HttpServletRequestFactory requestFactory;
@ -80,6 +84,17 @@ public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
/**
* Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
* the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.
*
* @since 5.8
*/
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
public void setRolePrefix(String rolePrefix) {
Assert.notNull(rolePrefix, "Role prefix must not be null");
this.rolePrefix = rolePrefix;
@ -178,6 +193,7 @@ public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
factory.setAuthenticationEntryPoint(this.authenticationEntryPoint);
factory.setAuthenticationManager(this.authenticationManager);
factory.setLogoutHandlers(this.logoutHandlers);
factory.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
return factory;
}

View File

@ -28,6 +28,7 @@ import org.springframework.security.authentication.AuthenticationTrustResolverIm
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;
@ -50,6 +51,9 @@ import org.springframework.util.Assert;
*/
public class SecurityContextHolderAwareRequestWrapper extends HttpServletRequestWrapper {
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private final AuthenticationTrustResolver trustResolver;
/**
@ -88,7 +92,7 @@ public class SecurityContextHolderAwareRequestWrapper extends HttpServletRequest
* @return the authentication object or <code>null</code>
*/
private Authentication getAuthentication() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Authentication auth = this.securityContextHolderStrategy.getContext().getAuthentication();
return (!this.trustResolver.isAnonymous(auth)) ? auth : null;
}
@ -169,4 +173,15 @@ public class SecurityContextHolderAwareRequestWrapper extends HttpServletRequest
return "SecurityContextHolderAwareRequestWrapper[ " + getRequest() + "]";
}
/**
* Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
* the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.
*
* @since 5.8
*/
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
}