Merge branch '5.8.x' into 6.0.x
Closes gh-13882
This commit is contained in:
@@ -148,7 +148,7 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
private static final String FILTER_APPLIED = FilterChainProxy.class.getName().concat(".APPLIED");
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private List<SecurityFilterChain> filterChains;
|
||||
|
||||
@@ -193,7 +193,7 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
catch (Exception ex) {
|
||||
Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(ex);
|
||||
Throwable requestRejectedException = this.throwableAnalyzer
|
||||
.getFirstThrowableOfType(RequestRejectedException.class, causeChain);
|
||||
.getFirstThrowableOfType(RequestRejectedException.class, causeChain);
|
||||
if (!(requestRejectedException instanceof RequestRejectedException)) {
|
||||
throw ex;
|
||||
}
|
||||
|
||||
@@ -336,17 +336,21 @@ public class FilterInvocation {
|
||||
return invokeDefaultMethodForJdk8(proxy, method, args);
|
||||
}
|
||||
return MethodHandles.lookup()
|
||||
.findSpecial(method.getDeclaringClass(), method.getName(),
|
||||
MethodType.methodType(method.getReturnType(), new Class[0]), method.getDeclaringClass())
|
||||
.bindTo(proxy).invokeWithArguments(args);
|
||||
.findSpecial(method.getDeclaringClass(), method.getName(),
|
||||
MethodType.methodType(method.getReturnType(), new Class[0]), method.getDeclaringClass())
|
||||
.bindTo(proxy)
|
||||
.invokeWithArguments(args);
|
||||
}
|
||||
|
||||
private Object invokeDefaultMethodForJdk8(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class);
|
||||
constructor.setAccessible(true);
|
||||
Class<?> clazz = method.getDeclaringClass();
|
||||
return constructor.newInstance(clazz).in(clazz).unreflectSpecial(method, clazz).bindTo(proxy)
|
||||
.invokeWithArguments(args);
|
||||
return constructor.newInstance(clazz)
|
||||
.in(clazz)
|
||||
.unreflectSpecial(method, clazz)
|
||||
.bindTo(proxy)
|
||||
.invokeWithArguments(args);
|
||||
}
|
||||
|
||||
private boolean isJdk8OrEarlier() {
|
||||
|
||||
+6
-6
@@ -76,7 +76,7 @@ public final class ObservationFilterChainDecorator implements FilterChainProxy.F
|
||||
return (req, res) -> {
|
||||
AroundFilterObservation parent = observation((HttpServletRequest) req);
|
||||
Observation observation = Observation.createNotStarted(SECURED_OBSERVATION_NAME, this.registry)
|
||||
.contextualName("secured request");
|
||||
.contextualName("secured request");
|
||||
parent.wrap(FilterObservation.create(observation).wrap(original)).doFilter(req, res);
|
||||
};
|
||||
}
|
||||
@@ -84,7 +84,7 @@ public final class ObservationFilterChainDecorator implements FilterChainProxy.F
|
||||
private FilterChain wrapUnsecured(FilterChain original) {
|
||||
return (req, res) -> {
|
||||
Observation observation = Observation.createNotStarted(UNSECURED_OBSERVATION_NAME, this.registry)
|
||||
.contextualName("unsecured request");
|
||||
.contextualName("unsecured request");
|
||||
FilterObservation.create(observation).wrap(original).doFilter(req, res);
|
||||
};
|
||||
}
|
||||
@@ -518,10 +518,10 @@ public final class ObservationFilterChainDecorator implements FilterChainProxy.F
|
||||
@Override
|
||||
public KeyValues getLowCardinalityKeyValues(FilterChainObservationContext context) {
|
||||
return KeyValues.of(CHAIN_SIZE_NAME, String.valueOf(context.getChainSize()))
|
||||
.and(CHAIN_POSITION_NAME, String.valueOf(context.getChainPosition()))
|
||||
.and(FILTER_SECTION_NAME, context.getFilterSection())
|
||||
.and(FILTER_NAME, (StringUtils.hasText(context.getFilterName())) ? context.getFilterName()
|
||||
: KeyValue.NONE_VALUE);
|
||||
.and(CHAIN_POSITION_NAME, String.valueOf(context.getChainPosition()))
|
||||
.and(FILTER_SECTION_NAME, context.getFilterSection())
|
||||
.and(FILTER_NAME,
|
||||
(StringUtils.hasText(context.getFilterName())) ? context.getFilterName() : KeyValue.NONE_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ public class DefaultWebInvocationPrivilegeEvaluator implements WebInvocationPriv
|
||||
Assert.notNull(uri, "uri parameter is required");
|
||||
FilterInvocation filterInvocation = new FilterInvocation(contextPath, uri, method, this.servletContext);
|
||||
Collection<ConfigAttribute> attributes = this.securityInterceptor.obtainSecurityMetadataSource()
|
||||
.getAttributes(filterInvocation);
|
||||
.getAttributes(filterInvocation);
|
||||
if (attributes == null) {
|
||||
return (!this.securityInterceptor.isRejectPublicInvocations());
|
||||
}
|
||||
|
||||
+3
-3
@@ -84,7 +84,7 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
public class ExceptionTranslationFilter extends GenericFilterBean implements MessageSourceAware {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerImpl();
|
||||
|
||||
@@ -132,10 +132,10 @@ public class ExceptionTranslationFilter extends GenericFilterBean implements Mes
|
||||
// Try to extract a SpringSecurityException from the stacktrace
|
||||
Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(ex);
|
||||
RuntimeException securityException = (AuthenticationException) this.throwableAnalyzer
|
||||
.getFirstThrowableOfType(AuthenticationException.class, causeChain);
|
||||
.getFirstThrowableOfType(AuthenticationException.class, causeChain);
|
||||
if (securityException == null) {
|
||||
securityException = (AccessDeniedException) this.throwableAnalyzer
|
||||
.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
|
||||
.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
|
||||
}
|
||||
if (securityException == null) {
|
||||
rethrow(ex);
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ public final class WebExpressionAuthorizationManager implements AuthorizationMan
|
||||
Assert.notNull(expressionHandler, "expressionHandler cannot be null");
|
||||
this.expressionHandler = expressionHandler;
|
||||
this.expression = expressionHandler.getExpressionParser()
|
||||
.parseExpression(this.expression.getExpressionString());
|
||||
.parseExpression(this.expression.getExpressionString());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ public class WebExpressionVoter implements AccessDecisionVoter<FilterInvocation>
|
||||
WebExpressionConfigAttribute webExpressionConfigAttribute = findConfigAttribute(attributes);
|
||||
if (webExpressionConfigAttribute == null) {
|
||||
this.logger
|
||||
.trace("Abstained since did not find a config attribute of instance WebExpressionConfigAttribute");
|
||||
.trace("Abstained since did not find a config attribute of instance WebExpressionConfigAttribute");
|
||||
return ACCESS_ABSTAIN;
|
||||
}
|
||||
EvaluationContext ctx = webExpressionConfigAttribute.postProcess(
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
public class AuthorizationFilter extends GenericFilterBean {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private final AuthorizationManager<HttpServletRequest> authorizationManager;
|
||||
|
||||
|
||||
+2
-1
@@ -31,7 +31,8 @@ class WebMvcSecurityRuntimeHints implements RuntimeHintsRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
hints.reflection().registerType(WebSecurityExpressionRoot.class, (builder) -> builder
|
||||
hints.reflection()
|
||||
.registerType(WebSecurityExpressionRoot.class, (builder) -> builder
|
||||
.withMembers(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.DECLARED_FIELDS));
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -116,7 +116,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
implements ApplicationEventPublisherAware, MessageSourceAware {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
protected ApplicationEventPublisher eventPublisher;
|
||||
|
||||
@@ -268,7 +268,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
}
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger
|
||||
.trace(LogMessage.format("Did not match request to %s", this.requiresAuthenticationRequestMatcher));
|
||||
.trace(LogMessage.format("Did not match request to %s", this.requiresAuthenticationRequestMatcher));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+2
-2
@@ -51,7 +51,7 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
public class AnonymousAuthenticationFilter extends GenericFilterBean implements InitializingBean {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
|
||||
|
||||
@@ -96,7 +96,7 @@ public class AnonymousAuthenticationFilter extends GenericFilterBean implements
|
||||
throws IOException, ServletException {
|
||||
Supplier<SecurityContext> deferredContext = this.securityContextHolderStrategy.getDeferredContext();
|
||||
this.securityContextHolderStrategy
|
||||
.setDeferredContext(defaultWithAnonymous((HttpServletRequest) req, deferredContext));
|
||||
.setDeferredContext(defaultWithAnonymous((HttpServletRequest) req, deferredContext));
|
||||
chain.doFilter(req, res);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
||||
public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE;
|
||||
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ public class DelegatingAuthenticationFailureHandler implements AuthenticationFai
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException exception) throws IOException, ServletException {
|
||||
for (Map.Entry<Class<? extends AuthenticationException>, AuthenticationFailureHandler> entry : this.handlers
|
||||
.entrySet()) {
|
||||
.entrySet()) {
|
||||
Class<? extends AuthenticationException> handlerMappedExceptionClass = entry.getKey();
|
||||
if (handlerMappedExceptionClass.isAssignableFrom(exception.getClass())) {
|
||||
AuthenticationFailureHandler handler = entry.getValue();
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
public class LogoutFilter extends GenericFilterBean {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private RequestMatcher logoutRequestMatcher;
|
||||
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ public class SecurityContextLogoutHandler implements LogoutHandler {
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private boolean invalidateHttpSession = true;
|
||||
|
||||
|
||||
+6
-5
@@ -90,7 +90,7 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
implements ApplicationEventPublisherAware {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private ApplicationEventPublisher eventPublisher = null;
|
||||
|
||||
@@ -136,8 +136,8 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
throws IOException, ServletException {
|
||||
if (this.requiresAuthenticationRequestMatcher.matches((HttpServletRequest) request)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(LogMessage.of(
|
||||
() -> "Authenticating " + this.securityContextHolderStrategy.getContext().getAuthentication()));
|
||||
logger.debug(LogMessage
|
||||
.of(() -> "Authenticating " + this.securityContextHolderStrategy.getContext().getAuthentication()));
|
||||
}
|
||||
doAuthenticate((HttpServletRequest) request, (HttpServletResponse) response);
|
||||
}
|
||||
@@ -370,7 +370,8 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
Authentication currentUser = AbstractPreAuthenticatedProcessingFilter.this.securityContextHolderStrategy
|
||||
.getContext().getAuthentication();
|
||||
.getContext()
|
||||
.getAuthentication();
|
||||
if (currentUser == null) {
|
||||
return true;
|
||||
}
|
||||
@@ -381,7 +382,7 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
return false;
|
||||
}
|
||||
AbstractPreAuthenticatedProcessingFilter.this.logger
|
||||
.debug("Pre-authenticated principal has changed and will be reauthenticated");
|
||||
.debug("Pre-authenticated principal has changed and will be reauthenticated");
|
||||
if (AbstractPreAuthenticatedProcessingFilter.this.invalidateSessionOnPrincipalChange) {
|
||||
AbstractPreAuthenticatedProcessingFilter.this.securityContextHolderStrategy.clearContext();
|
||||
HttpSession session = request.getSession(false);
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
|
||||
return null;
|
||||
}
|
||||
UserDetails userDetails = this.preAuthenticatedUserDetailsService
|
||||
.loadUserDetails((PreAuthenticatedAuthenticationToken) authentication);
|
||||
.loadUserDetails((PreAuthenticatedAuthenticationToken) authentication);
|
||||
this.userDetailsChecker.check(userDetails);
|
||||
PreAuthenticatedAuthenticationToken result = new PreAuthenticatedAuthenticationToken(userDetails,
|
||||
authentication.getCredentials(), userDetails.getAuthorities());
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class PreAuthenticatedGrantedAuthoritiesUserDetailsService
|
||||
Assert.notNull(token.getDetails(), "token.getDetails() cannot be null");
|
||||
Assert.isInstanceOf(GrantedAuthoritiesContainer.class, token.getDetails());
|
||||
Collection<? extends GrantedAuthority> authorities = ((GrantedAuthoritiesContainer) token.getDetails())
|
||||
.getGrantedAuthorities();
|
||||
.getGrantedAuthorities();
|
||||
return createUserDetails(token, authorities);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -93,7 +93,7 @@ public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource implements
|
||||
public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails buildDetails(HttpServletRequest context) {
|
||||
Collection<String> j2eeUserRoles = getUserRoles(context);
|
||||
Collection<? extends GrantedAuthority> userGrantedAuthorities = this.j2eeUserRoles2GrantedAuthoritiesMapper
|
||||
.getGrantedAuthorities(j2eeUserRoles);
|
||||
.getGrantedAuthorities(j2eeUserRoles);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(LogMessage.format("J2EE roles [%s] mapped to Granted Authorities: [%s]", j2eeUserRoles,
|
||||
userGrantedAuthorities));
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ public class WebSpherePreAuthenticatedWebAuthenticationDetailsSource implements
|
||||
private Collection<? extends GrantedAuthority> getWebSphereGroupsBasedGrantedAuthorities() {
|
||||
List<String> webSphereGroups = this.wasHelper.getGroupsForCurrentUser();
|
||||
Collection<? extends GrantedAuthority> userGas = this.webSphereGroups2GrantedAuthoritiesMapper
|
||||
.getGrantedAuthorities(webSphereGroups);
|
||||
.getGrantedAuthorities(webSphereGroups);
|
||||
this.logger.debug(
|
||||
LogMessage.format("WebSphere groups: %s mapped to Granted Authorities: %s", webSphereGroups, userGas));
|
||||
return userGas;
|
||||
|
||||
+1
-1
@@ -388,7 +388,7 @@ public abstract class AbstractRememberMeServices
|
||||
@Override
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
|
||||
this.logger.debug(LogMessage
|
||||
.of(() -> "Logout of user " + ((authentication != null) ? authentication.getName() : "Unknown")));
|
||||
.of(() -> "Logout of user " + ((authentication != null) ? authentication.getName() : "Unknown")));
|
||||
cancelCookie(request, response);
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -69,7 +69,7 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
public class RememberMeAuthenticationFilter extends GenericFilterBean implements ApplicationEventPublisherAware {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
|
||||
@@ -105,8 +105,8 @@ public class RememberMeAuthenticationFilter extends GenericFilterBean implements
|
||||
throws IOException, ServletException {
|
||||
if (this.securityContextHolderStrategy.getContext().getAuthentication() != null) {
|
||||
this.logger.debug(LogMessage
|
||||
.of(() -> "SecurityContextHolder not populated with remember-me token, as it already contained: '"
|
||||
+ this.securityContextHolderStrategy.getContext().getAuthentication() + "'"));
|
||||
.of(() -> "SecurityContextHolder not populated with remember-me token, as it already contained: '"
|
||||
+ this.securityContextHolderStrategy.getContext().getAuthentication() + "'"));
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
@@ -134,9 +134,9 @@ public class RememberMeAuthenticationFilter extends GenericFilterBean implements
|
||||
}
|
||||
catch (AuthenticationException ex) {
|
||||
this.logger.debug(LogMessage
|
||||
.format("SecurityContextHolder not populated with remember-me token, as AuthenticationManager "
|
||||
+ "rejected Authentication returned by RememberMeServices: '%s'; "
|
||||
+ "invalidating remember-me token", rememberMeAuth),
|
||||
.format("SecurityContextHolder not populated with remember-me token, as AuthenticationManager "
|
||||
+ "rejected Authentication returned by RememberMeServices: '%s'; "
|
||||
+ "invalidating remember-me token", rememberMeAuth),
|
||||
ex);
|
||||
this.rememberMeServices.loginFail(request, response);
|
||||
onUnsuccessfulAuthentication(request, response, ex);
|
||||
|
||||
+2
-2
@@ -238,8 +238,8 @@ public class TokenBasedRememberMeServices extends AbstractRememberMeServices {
|
||||
setCookie(new String[] { username, Long.toString(expiryTime), this.encodingAlgorithm.name(), signatureValue },
|
||||
tokenLifetime, request, response);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(
|
||||
"Added remember-me cookie for user '" + username + "', expiry: '" + new Date(expiryTime) + "'");
|
||||
this.logger
|
||||
.debug("Added remember-me cookie for user '" + username + "', expiry: '" + new Date(expiryTime) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ public abstract class AbstractSessionFixationProtectionStrategy
|
||||
*/
|
||||
protected void onSessionChange(String originalSessionId, HttpSession newSession, Authentication auth) {
|
||||
this.applicationEventPublisher
|
||||
.publishEvent(new SessionFixationProtectionEvent(auth, originalSessionId, newSession.getId()));
|
||||
.publishEvent(new SessionFixationProtectionEvent(auth, originalSessionId, newSession.getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-3
@@ -119,7 +119,7 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv
|
||||
public static final String ROLE_PREVIOUS_ADMINISTRATOR = "ROLE_PREVIOUS_ADMINISTRATOR";
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
|
||||
@@ -258,7 +258,7 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv
|
||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (current == null) {
|
||||
throw new AuthenticationCredentialsNotFoundException(this.messages
|
||||
.getMessage("SwitchUserFilter.noCurrentUser", "No current user associated with this request"));
|
||||
.getMessage("SwitchUserFilter.noCurrentUser", "No current user associated with this request"));
|
||||
}
|
||||
// check to see if the current user did actual switch to another user
|
||||
// if so, get the original source user so we can switch back
|
||||
@@ -266,7 +266,7 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv
|
||||
if (original == null) {
|
||||
this.logger.debug("Failed to find original user");
|
||||
throw new AuthenticationCredentialsNotFoundException(this.messages
|
||||
.getMessage("SwitchUserFilter.noOriginalAuthentication", "Failed to find original user"));
|
||||
.getMessage("SwitchUserFilter.noOriginalAuthentication", "Failed to find original user"));
|
||||
}
|
||||
// get the source user details
|
||||
UserDetails originalUser = null;
|
||||
|
||||
+3
-3
@@ -194,7 +194,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
AuthenticationException ex = (AuthenticationException) session
|
||||
.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
|
||||
.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
|
||||
errorMsg = (ex != null) ? ex.getMessage() : "Invalid credentials";
|
||||
}
|
||||
}
|
||||
@@ -239,7 +239,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
||||
sb.append(createLogoutSuccess(logoutSuccess));
|
||||
sb.append("<table class=\"table table-striped\">\n");
|
||||
for (Map.Entry<String, String> clientAuthenticationUrlToClientName : this.oauth2AuthenticationUrlToClientName
|
||||
.entrySet()) {
|
||||
.entrySet()) {
|
||||
sb.append(" <tr><td>");
|
||||
String url = clientAuthenticationUrlToClientName.getKey();
|
||||
sb.append("<a href=\"").append(contextPath).append(url).append("\">");
|
||||
@@ -256,7 +256,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
||||
sb.append(createLogoutSuccess(logoutSuccess));
|
||||
sb.append("<table class=\"table table-striped\">\n");
|
||||
for (Map.Entry<String, String> relyingPartyUrlToName : this.saml2AuthenticationUrlToProviderName
|
||||
.entrySet()) {
|
||||
.entrySet()) {
|
||||
sb.append(" <tr><td>");
|
||||
String url = relyingPartyUrlToName.getKey();
|
||||
sb.append("<a href=\"").append(contextPath).append(url).append("\">");
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ public class BasicAuthenticationConverter implements AuthenticationConverter {
|
||||
throw new BadCredentialsException("Invalid basic authentication token");
|
||||
}
|
||||
UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken
|
||||
.unauthenticated(token.substring(0, delim), token.substring(delim + 1));
|
||||
.unauthenticated(token.substring(0, delim), token.substring(delim + 1));
|
||||
result.setDetails(this.authenticationDetailsSource.buildDetails(request));
|
||||
return result;
|
||||
}
|
||||
|
||||
+1
-1
@@ -93,7 +93,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
||||
public class BasicAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private AuthenticationEntryPoint authenticationEntryPoint;
|
||||
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ public class DigestAuthenticationFilter extends GenericFilterBean implements Mes
|
||||
private static final Log logger = LogFactory.getLog(DigestAuthenticationFilter.class);
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
|
||||
|
||||
|
||||
+1
-1
@@ -29,9 +29,9 @@ import org.springframework.security.core.Authentication;
|
||||
* {@link Authentication#getPrincipal()}. This is necessary to signal that the argument
|
||||
* should be resolved to the current user rather than a user that might be edited on a
|
||||
* form.
|
||||
*
|
||||
* @deprecated Use
|
||||
* {@link org.springframework.security.core.annotation.AuthenticationPrincipal} instead.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
|
||||
+3
-3
@@ -93,7 +93,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
/**
|
||||
* SecurityContext instance used to check for equality with default (unauthenticated)
|
||||
@@ -227,8 +227,8 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(
|
||||
LogMessage.format("Retrieved %s from %s", contextFromSession, this.springSecurityContextKey));
|
||||
this.logger
|
||||
.trace(LogMessage.format("Retrieved %s from %s", contextFromSession, this.springSecurityContextKey));
|
||||
}
|
||||
else if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(LogMessage.format("Retrieved %s", contextFromSession));
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ import org.springframework.util.Assert;
|
||||
public final class NullSecurityContextRepository implements SecurityContextRepository {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
@Override
|
||||
public boolean containsContext(HttpServletRequest request) {
|
||||
|
||||
+2
-2
@@ -47,12 +47,12 @@ public final class RequestAttributeSecurityContextRepository implements Security
|
||||
* The default request attribute name to use.
|
||||
*/
|
||||
public static final String DEFAULT_REQUEST_ATTR_NAME = RequestAttributeSecurityContextRepository.class.getName()
|
||||
.concat(".SPRING_SECURITY_CONTEXT");
|
||||
.concat(".SPRING_SECURITY_CONTEXT");
|
||||
|
||||
private final String requestAttributeName;
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
/**
|
||||
* Creates a new instance using {@link #DEFAULT_REQUEST_ATTR_NAME}.
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ import org.springframework.util.Assert;
|
||||
public abstract class SaveContextOnUpdateOrErrorResponseWrapper extends OnCommittedResponseWrapper {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private boolean contextSaved = false;
|
||||
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ public class SecurityContextHolderFilter extends GenericFilterBean {
|
||||
private final SecurityContextRepository securityContextRepository;
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
|
||||
+2
-2
@@ -69,7 +69,7 @@ public class SecurityContextPersistenceFilter extends GenericFilterBean {
|
||||
private SecurityContextRepository repo;
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private boolean forceEagerSessionCreation = false;
|
||||
|
||||
@@ -111,7 +111,7 @@ public class SecurityContextPersistenceFilter extends GenericFilterBean {
|
||||
else {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger
|
||||
.debug(LogMessage.format("Set SecurityContextHolder to %s", contextBeforeChainExecution));
|
||||
.debug(LogMessage.format("Set SecurityContextHolder to %s", contextBeforeChainExecution));
|
||||
}
|
||||
}
|
||||
chain.doFilter(holder.getRequest(), holder.getResponse());
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ public final class SecurityContextCallableProcessingInterceptor implements Calla
|
||||
private volatile SecurityContext securityContext;
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
/**
|
||||
* Create a new {@link SecurityContextCallableProcessingInterceptor} that uses the
|
||||
|
||||
+2
-2
@@ -46,14 +46,14 @@ public final class WebAsyncManagerIntegrationFilter extends OncePerRequestFilter
|
||||
private static final Object CALLABLE_INTERCEPTOR_KEY = new Object();
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
|
||||
SecurityContextCallableProcessingInterceptor securityProcessingInterceptor = (SecurityContextCallableProcessingInterceptor) asyncManager
|
||||
.getCallableInterceptor(CALLABLE_INTERCEPTOR_KEY);
|
||||
.getCallableInterceptor(CALLABLE_INTERCEPTOR_KEY);
|
||||
if (securityProcessingInterceptor == null) {
|
||||
SecurityContextCallableProcessingInterceptor interceptor = new SecurityContextCallableProcessingInterceptor();
|
||||
interceptor.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ public final class CookieCsrfTokenRepository implements CsrfTokenRepository {
|
||||
static final String DEFAULT_CSRF_HEADER_NAME = "X-XSRF-TOKEN";
|
||||
|
||||
private static final String CSRF_TOKEN_REMOVED_ATTRIBUTE_NAME = CookieCsrfTokenRepository.class.getName()
|
||||
.concat(".REMOVED");
|
||||
.concat(".REMOVED");
|
||||
|
||||
private String parameterName = DEFAULT_CSRF_PARAMETER_NAME;
|
||||
|
||||
|
||||
@@ -121,8 +121,8 @@ public final class CsrfFilter extends OncePerRequestFilter {
|
||||
String actualToken = this.requestHandler.resolveCsrfTokenValue(request, csrfToken);
|
||||
if (!equalsConstantTime(csrfToken.getToken(), actualToken)) {
|
||||
boolean missingToken = deferredCsrfToken.isGenerated();
|
||||
this.logger.debug(
|
||||
LogMessage.of(() -> "Invalid CSRF token found for " + UrlUtils.buildFullRequestUrl(request)));
|
||||
this.logger
|
||||
.debug(LogMessage.of(() -> "Invalid CSRF token found for " + UrlUtils.buildFullRequestUrl(request)));
|
||||
AccessDeniedException exception = (!missingToken) ? new InvalidCsrfTokenException(csrfToken, actualToken)
|
||||
: new MissingCsrfTokenException(actualToken);
|
||||
this.accessDeniedHandler.handle(request, response, exception);
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ public final class HttpSessionCsrfTokenRepository implements CsrfTokenRepository
|
||||
private static final String DEFAULT_CSRF_HEADER_NAME = "X-CSRF-TOKEN";
|
||||
|
||||
private static final String DEFAULT_CSRF_TOKEN_ATTR_NAME = HttpSessionCsrfTokenRepository.class.getName()
|
||||
.concat(".CSRF_TOKEN");
|
||||
.concat(".CSRF_TOKEN");
|
||||
|
||||
private String parameterName = DEFAULT_CSRF_PARAMETER_NAME;
|
||||
|
||||
|
||||
@@ -91,19 +91,19 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||
private static final String PERCENT = "%";
|
||||
|
||||
private static final List<String> FORBIDDEN_ENCODED_PERIOD = Collections
|
||||
.unmodifiableList(Arrays.asList("%2e", "%2E"));
|
||||
.unmodifiableList(Arrays.asList("%2e", "%2E"));
|
||||
|
||||
private static final List<String> FORBIDDEN_SEMICOLON = Collections
|
||||
.unmodifiableList(Arrays.asList(";", "%3b", "%3B"));
|
||||
.unmodifiableList(Arrays.asList(";", "%3b", "%3B"));
|
||||
|
||||
private static final List<String> FORBIDDEN_FORWARDSLASH = Collections
|
||||
.unmodifiableList(Arrays.asList("%2f", "%2F"));
|
||||
.unmodifiableList(Arrays.asList("%2f", "%2F"));
|
||||
|
||||
private static final List<String> FORBIDDEN_DOUBLE_FORWARDSLASH = Collections
|
||||
.unmodifiableList(Arrays.asList("//", "%2f%2f", "%2f%2F", "%2F%2f", "%2F%2F"));
|
||||
.unmodifiableList(Arrays.asList("//", "%2f%2f", "%2f%2F", "%2F%2f", "%2F%2F"));
|
||||
|
||||
private static final List<String> FORBIDDEN_BACKSLASH = Collections
|
||||
.unmodifiableList(Arrays.asList("\\", "%5c", "%5C"));
|
||||
.unmodifiableList(Arrays.asList("\\", "%5c", "%5C"));
|
||||
|
||||
private static final List<String> FORBIDDEN_NULL = Collections.unmodifiableList(Arrays.asList("\0", "%00"));
|
||||
|
||||
@@ -114,7 +114,7 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||
private static final List<String> FORBIDDEN_LINE_SEPARATOR = Collections.unmodifiableList(Arrays.asList("\u2028"));
|
||||
|
||||
private static final List<String> FORBIDDEN_PARAGRAPH_SEPARATOR = Collections
|
||||
.unmodifiableList(Arrays.asList("\u2029"));
|
||||
.unmodifiableList(Arrays.asList("\u2029"));
|
||||
|
||||
private Set<String> encodedUrlBlocklist = new HashSet<>();
|
||||
|
||||
@@ -125,7 +125,7 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||
private Predicate<String> allowedHostnames = (hostname) -> true;
|
||||
|
||||
private static final Pattern ASSIGNED_AND_NOT_ISO_CONTROL_PATTERN = Pattern
|
||||
.compile("[\\p{IsAssigned}&&[^\\p{IsControl}]]*");
|
||||
.compile("[\\p{IsAssigned}&&[^\\p{IsControl}]]*");
|
||||
|
||||
private static final Predicate<String> ASSIGNED_AND_NOT_ISO_CONTROL_PREDICATE = (
|
||||
s) -> ASSIGNED_AND_NOT_ISO_CONTROL_PATTERN.matcher(s).matches();
|
||||
@@ -513,8 +513,8 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||
|
||||
private void rejectNonPrintableAsciiCharactersInFieldName(String toCheck, String propertyName) {
|
||||
if (!containsOnlyPrintableAsciiCharacters(toCheck)) {
|
||||
throw new RequestRejectedException(String.format(
|
||||
"The %s was rejected because it can only contain printable ASCII characters.", propertyName));
|
||||
throw new RequestRejectedException(String
|
||||
.format("The %s was rejected because it can only contain printable ASCII characters.", propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
public class JaasApiIntegrationFilter extends GenericFilterBean {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private boolean createEmptySubject;
|
||||
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
public final class AuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private ExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
public final class CurrentSecurityContextArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private ExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
|
||||
+6
-6
@@ -73,12 +73,12 @@ public class AuthenticationPrincipalArgumentResolver extends HandlerMethodArgume
|
||||
public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext bindingContext,
|
||||
ServerWebExchange exchange) {
|
||||
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(parameter.getParameterType());
|
||||
return ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication)
|
||||
.flatMap((authentication) -> {
|
||||
Mono<Object> principal = Mono
|
||||
.justOrEmpty(resolvePrincipal(parameter, authentication.getPrincipal()));
|
||||
return (adapter != null) ? Mono.just(adapter.fromPublisher(principal)) : principal;
|
||||
});
|
||||
return ReactiveSecurityContextHolder.getContext()
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.flatMap((authentication) -> {
|
||||
Mono<Object> principal = Mono.justOrEmpty(resolvePrincipal(parameter, authentication.getPrincipal()));
|
||||
return (adapter != null) ? Mono.just(adapter.fromPublisher(principal)) : principal;
|
||||
});
|
||||
}
|
||||
|
||||
private Object resolvePrincipal(MethodParameter parameter, Object principal) {
|
||||
|
||||
+8
-3
@@ -76,9 +76,14 @@ public class CookieRequestCache implements RequestCache {
|
||||
UriComponents uriComponents = UriComponentsBuilder.fromUriString(originalURI).build();
|
||||
DefaultSavedRequest.Builder builder = new DefaultSavedRequest.Builder();
|
||||
int port = getPort(uriComponents);
|
||||
return builder.setScheme(uriComponents.getScheme()).setServerName(uriComponents.getHost())
|
||||
.setRequestURI(uriComponents.getPath()).setQueryString(uriComponents.getQuery()).setServerPort(port)
|
||||
.setMethod(request.getMethod()).setLocales(Collections.list(request.getLocales())).build();
|
||||
return builder.setScheme(uriComponents.getScheme())
|
||||
.setServerName(uriComponents.getHost())
|
||||
.setRequestURI(uriComponents.getPath())
|
||||
.setQueryString(uriComponents.getQuery())
|
||||
.setServerPort(port)
|
||||
.setMethod(request.getMethod())
|
||||
.setLocales(Collections.list(request.getLocales()))
|
||||
.build();
|
||||
}
|
||||
|
||||
private int getPort(UriComponents uriComponents) {
|
||||
|
||||
+6
-2
@@ -372,8 +372,12 @@ public class DefaultSavedRequest implements SavedRequest {
|
||||
if (queryString == null || queryString.length() == 0) {
|
||||
return matchingRequestParameterName;
|
||||
}
|
||||
return UriComponentsBuilder.newInstance().query(queryString).replaceQueryParam(matchingRequestParameterName)
|
||||
.queryParam(matchingRequestParameterName).build().getQuery();
|
||||
return UriComponentsBuilder.newInstance()
|
||||
.query(queryString)
|
||||
.replaceQueryParam(matchingRequestParameterName)
|
||||
.queryParam(matchingRequestParameterName)
|
||||
.build()
|
||||
.getQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-4
@@ -63,8 +63,8 @@ public class HttpSessionRequestCache implements RequestCache {
|
||||
public void saveRequest(HttpServletRequest request, HttpServletResponse response) {
|
||||
if (!this.requestMatcher.matches(request)) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(
|
||||
LogMessage.format("Did not save request since it did not match [%s]", this.requestMatcher));
|
||||
this.logger
|
||||
.trace(LogMessage.format("Did not save request since it did not match [%s]", this.requestMatcher));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -104,8 +104,10 @@ public class HttpSessionRequestCache implements RequestCache {
|
||||
public HttpServletRequest getMatchingRequest(HttpServletRequest request, HttpServletResponse response) {
|
||||
if (this.matchingRequestParameterName != null) {
|
||||
if (!StringUtils.hasText(request.getQueryString())
|
||||
|| !UriComponentsBuilder.fromUriString(UrlUtils.buildRequestUrl(request)).build().getQueryParams()
|
||||
.containsKey(this.matchingRequestParameterName)) {
|
||||
|| !UriComponentsBuilder.fromUriString(UrlUtils.buildRequestUrl(request))
|
||||
.build()
|
||||
.getQueryParams()
|
||||
.containsKey(this.matchingRequestParameterName)) {
|
||||
this.logger.trace(
|
||||
"matchingRequestParameterName is required for getMatchingRequest to lookup a value, but not provided");
|
||||
return null;
|
||||
|
||||
+9
-7
@@ -62,13 +62,15 @@ public class DelegatingServerAuthenticationEntryPoint implements ServerAuthentic
|
||||
|
||||
@Override
|
||||
public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException ex) {
|
||||
return Flux.fromIterable(this.entryPoints).filterWhen((entry) -> isMatch(exchange, entry)).next()
|
||||
.map((entry) -> entry.getEntryPoint())
|
||||
.doOnNext((entryPoint) -> logger.debug(LogMessage.format("Match found! Executing %s", entryPoint)))
|
||||
.switchIfEmpty(Mono.just(this.defaultEntryPoint)
|
||||
.doOnNext((entryPoint) -> logger.debug(LogMessage
|
||||
.format("No match found. Using default entry point %s", this.defaultEntryPoint))))
|
||||
.flatMap((entryPoint) -> entryPoint.commence(exchange, ex));
|
||||
return Flux.fromIterable(this.entryPoints)
|
||||
.filterWhen((entry) -> isMatch(exchange, entry))
|
||||
.next()
|
||||
.map((entry) -> entry.getEntryPoint())
|
||||
.doOnNext((entryPoint) -> logger.debug(LogMessage.format("Match found! Executing %s", entryPoint)))
|
||||
.switchIfEmpty(Mono.just(this.defaultEntryPoint)
|
||||
.doOnNext((entryPoint) -> logger
|
||||
.debug(LogMessage.format("No match found. Using default entry point %s", this.defaultEntryPoint))))
|
||||
.flatMap((entryPoint) -> entryPoint.commence(exchange, ex));
|
||||
}
|
||||
|
||||
private Mono<Boolean> isMatch(ServerWebExchange exchange, DelegateEntry entry) {
|
||||
|
||||
+25
-19
@@ -81,7 +81,8 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
|
||||
AroundWebFilterObservation parent = observation(exchange);
|
||||
Observation parentObservation = contextView.getOrDefault(ObservationThreadLocalAccessor.KEY, null);
|
||||
Observation observation = Observation.createNotStarted(SECURED_OBSERVATION_NAME, this.registry)
|
||||
.contextualName("secured request").parentObservation(parentObservation);
|
||||
.contextualName("secured request")
|
||||
.parentObservation(parentObservation);
|
||||
return parent.wrap(WebFilterObservation.create(observation).wrap(original)).filter(exchange);
|
||||
});
|
||||
}
|
||||
@@ -90,7 +91,8 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
|
||||
return (exchange) -> Mono.deferContextual((contextView) -> {
|
||||
Observation parentObservation = contextView.getOrDefault(ObservationThreadLocalAccessor.KEY, null);
|
||||
Observation observation = Observation.createNotStarted(UNSECURED_OBSERVATION_NAME, this.registry)
|
||||
.contextualName("unsecured request").parentObservation(parentObservation);
|
||||
.contextualName("unsecured request")
|
||||
.parentObservation(parentObservation);
|
||||
return WebFilterObservation.create(observation).wrap(original).filter(exchange);
|
||||
});
|
||||
}
|
||||
@@ -224,9 +226,9 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
|
||||
WebFilterChainObservationContext beforeContext = WebFilterChainObservationContext.before();
|
||||
WebFilterChainObservationContext afterContext = WebFilterChainObservationContext.after();
|
||||
Observation before = Observation.createNotStarted(this.convention, () -> beforeContext, this.registry)
|
||||
.parentObservation(parentObservation);
|
||||
.parentObservation(parentObservation);
|
||||
Observation after = Observation.createNotStarted(this.convention, () -> afterContext, this.registry)
|
||||
.parentObservation(parentObservation);
|
||||
.parentObservation(parentObservation);
|
||||
AroundWebFilterObservation parent = AroundWebFilterObservation.create(before, after);
|
||||
exchange.getAttributes().put(ATTRIBUTE, parent);
|
||||
return parent;
|
||||
@@ -582,11 +584,13 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
|
||||
}
|
||||
return (exchange, chain) -> {
|
||||
this.observation.start();
|
||||
return filter.filter(exchange, chain).doOnSuccess((v) -> this.observation.stop())
|
||||
.doOnCancel(this.observation::stop).doOnError((t) -> {
|
||||
this.observation.error(t);
|
||||
this.observation.stop();
|
||||
});
|
||||
return filter.filter(exchange, chain)
|
||||
.doOnSuccess((v) -> this.observation.stop())
|
||||
.doOnCancel(this.observation::stop)
|
||||
.doOnError((t) -> {
|
||||
this.observation.error(t);
|
||||
this.observation.stop();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -597,12 +601,14 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
|
||||
}
|
||||
return (exchange) -> {
|
||||
this.observation.start();
|
||||
return chain.filter(exchange).doOnSuccess((v) -> this.observation.stop())
|
||||
.doOnCancel(this.observation::stop).doOnError((t) -> {
|
||||
this.observation.error(t);
|
||||
this.observation.stop();
|
||||
}).contextWrite(
|
||||
(context) -> context.put(ObservationThreadLocalAccessor.KEY, this.observation));
|
||||
return chain.filter(exchange)
|
||||
.doOnSuccess((v) -> this.observation.stop())
|
||||
.doOnCancel(this.observation::stop)
|
||||
.doOnError((t) -> {
|
||||
this.observation.error(t);
|
||||
this.observation.stop();
|
||||
})
|
||||
.contextWrite((context) -> context.put(ObservationThreadLocalAccessor.KEY, this.observation));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -688,10 +694,10 @@ public final class ObservationWebFilterChainDecorator implements WebFilterChainP
|
||||
@Override
|
||||
public KeyValues getLowCardinalityKeyValues(WebFilterChainObservationContext context) {
|
||||
return KeyValues.of(CHAIN_SIZE_NAME, String.valueOf(context.getChainSize()))
|
||||
.and(CHAIN_POSITION_NAME, String.valueOf(context.getChainPosition()))
|
||||
.and(FILTER_SECTION_NAME, context.getFilterSection())
|
||||
.and(FILTER_NAME, (StringUtils.hasText(context.getFilterName())) ? context.getFilterName()
|
||||
: KeyValue.NONE_VALUE);
|
||||
.and(CHAIN_POSITION_NAME, String.valueOf(context.getChainPosition()))
|
||||
.and(FILTER_SECTION_NAME, context.getFilterSection())
|
||||
.and(FILTER_NAME,
|
||||
(StringUtils.hasText(context.getFilterName())) ? context.getFilterName() : KeyValue.NONE_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -54,12 +54,13 @@ public class WebFilterChainProxy implements WebFilter {
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return Flux.fromIterable(this.filters)
|
||||
.filterWhen((securityWebFilterChain) -> securityWebFilterChain.matches(exchange)).next()
|
||||
.switchIfEmpty(
|
||||
Mono.defer(() -> this.filterChainDecorator.decorate(chain).filter(exchange).then(Mono.empty())))
|
||||
.flatMap((securityWebFilterChain) -> securityWebFilterChain.getWebFilters().collectList())
|
||||
.map((filters) -> this.filterChainDecorator.decorate(chain, filters))
|
||||
.flatMap((securedChain) -> securedChain.filter(exchange));
|
||||
.filterWhen((securityWebFilterChain) -> securityWebFilterChain.matches(exchange))
|
||||
.next()
|
||||
.switchIfEmpty(
|
||||
Mono.defer(() -> this.filterChainDecorator.decorate(chain).filter(exchange).then(Mono.empty())))
|
||||
.flatMap((securityWebFilterChain) -> securityWebFilterChain.getWebFilters().collectList())
|
||||
.map((filters) -> this.filterChainDecorator.decorate(chain, filters))
|
||||
.flatMap((securedChain) -> securedChain.filter(exchange));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -83,8 +83,8 @@ public class AnonymousAuthenticationWebFilter implements WebFilter {
|
||||
SecurityContext securityContext = new SecurityContextImpl(authentication);
|
||||
logger.debug(LogMessage.format("Populated SecurityContext with anonymous token: '%s'", authentication));
|
||||
return chain.filter(exchange)
|
||||
.contextWrite(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext)))
|
||||
.then(Mono.empty());
|
||||
.contextWrite(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext)))
|
||||
.then(Mono.empty());
|
||||
})).flatMap((securityContext) -> {
|
||||
logger.debug(LogMessage.format("SecurityContext contains anonymous token: '%s'",
|
||||
securityContext.getAuthentication()));
|
||||
|
||||
+4
-2
@@ -43,8 +43,10 @@ public final class AuthenticationConverterServerWebExchangeMatcher implements Se
|
||||
|
||||
@Override
|
||||
public Mono<MatchResult> matches(ServerWebExchange exchange) {
|
||||
return this.serverAuthenticationConverter.convert(exchange).flatMap((a) -> MatchResult.match())
|
||||
.onErrorResume((ex) -> MatchResult.notMatch()).switchIfEmpty(MatchResult.notMatch());
|
||||
return this.serverAuthenticationConverter.convert(exchange)
|
||||
.flatMap((a) -> MatchResult.match())
|
||||
.onErrorResume((ex) -> MatchResult.notMatch())
|
||||
.switchIfEmpty(MatchResult.notMatch());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+17
-16
@@ -82,7 +82,7 @@ public class AuthenticationWebFilter implements WebFilter {
|
||||
new HttpBasicServerAuthenticationEntryPoint());
|
||||
|
||||
private ServerSecurityContextRepository securityContextRepository = NoOpServerSecurityContextRepository
|
||||
.getInstance();
|
||||
.getInstance();
|
||||
|
||||
private ServerWebExchangeMatcher requiresAuthenticationMatcher = ServerWebExchangeMatchers.anyExchange();
|
||||
|
||||
@@ -108,23 +108,24 @@ public class AuthenticationWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return this.requiresAuthenticationMatcher.matches(exchange).filter((matchResult) -> matchResult.isMatch())
|
||||
.flatMap((matchResult) -> this.authenticationConverter.convert(exchange))
|
||||
.switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
|
||||
.flatMap((token) -> authenticate(exchange, chain, token))
|
||||
.onErrorResume(AuthenticationException.class, (ex) -> this.authenticationFailureHandler
|
||||
.onAuthenticationFailure(new WebFilterExchange(exchange, chain), ex));
|
||||
return this.requiresAuthenticationMatcher.matches(exchange)
|
||||
.filter((matchResult) -> matchResult.isMatch())
|
||||
.flatMap((matchResult) -> this.authenticationConverter.convert(exchange))
|
||||
.switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
|
||||
.flatMap((token) -> authenticate(exchange, chain, token))
|
||||
.onErrorResume(AuthenticationException.class, (ex) -> this.authenticationFailureHandler
|
||||
.onAuthenticationFailure(new WebFilterExchange(exchange, chain), ex));
|
||||
}
|
||||
|
||||
private Mono<Void> authenticate(ServerWebExchange exchange, WebFilterChain chain, Authentication token) {
|
||||
return this.authenticationManagerResolver.resolve(exchange)
|
||||
.flatMap((authenticationManager) -> authenticationManager.authenticate(token))
|
||||
.switchIfEmpty(Mono.defer(
|
||||
() -> Mono.error(new IllegalStateException("No provider found for " + token.getClass()))))
|
||||
.flatMap((authentication) -> onAuthenticationSuccess(authentication,
|
||||
new WebFilterExchange(exchange, chain)))
|
||||
.doOnError(AuthenticationException.class,
|
||||
(ex) -> logger.debug(LogMessage.format("Authentication failed: %s", ex.getMessage())));
|
||||
.flatMap((authenticationManager) -> authenticationManager.authenticate(token))
|
||||
.switchIfEmpty(Mono
|
||||
.defer(() -> Mono.error(new IllegalStateException("No provider found for " + token.getClass()))))
|
||||
.flatMap(
|
||||
(authentication) -> onAuthenticationSuccess(authentication, new WebFilterExchange(exchange, chain)))
|
||||
.doOnError(AuthenticationException.class,
|
||||
(ex) -> logger.debug(LogMessage.format("Authentication failed: %s", ex.getMessage())));
|
||||
}
|
||||
|
||||
protected Mono<Void> onAuthenticationSuccess(Authentication authentication, WebFilterExchange webFilterExchange) {
|
||||
@@ -132,8 +133,8 @@ public class AuthenticationWebFilter implements WebFilter {
|
||||
SecurityContextImpl securityContext = new SecurityContextImpl();
|
||||
securityContext.setAuthentication(authentication);
|
||||
return this.securityContextRepository.save(exchange, securityContext)
|
||||
.then(this.authenticationSuccessHandler.onAuthenticationSuccess(webFilterExchange, authentication))
|
||||
.contextWrite(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext)));
|
||||
.then(this.authenticationSuccessHandler.onAuthenticationSuccess(webFilterExchange, authentication))
|
||||
.contextWrite(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-1
@@ -45,7 +45,8 @@ public class DelegatingServerAuthenticationSuccessHandler implements ServerAuthe
|
||||
@Override
|
||||
public Mono<Void> onAuthenticationSuccess(WebFilterExchange exchange, Authentication authentication) {
|
||||
return Flux.fromIterable(this.delegates)
|
||||
.concatMap((delegate) -> delegate.onAuthenticationSuccess(exchange, authentication)).then();
|
||||
.concatMap((delegate) -> delegate.onAuthenticationSuccess(exchange, authentication))
|
||||
.then();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-9
@@ -58,15 +58,18 @@ public class ReactivePreAuthenticatedAuthenticationManager implements ReactiveAu
|
||||
|
||||
@Override
|
||||
public Mono<Authentication> authenticate(Authentication authentication) {
|
||||
return Mono.just(authentication).filter(this::supports).map(Authentication::getName)
|
||||
.flatMap(this.userDetailsService::findByUsername)
|
||||
.switchIfEmpty(Mono.error(() -> new UsernameNotFoundException("User not found")))
|
||||
.doOnNext(this.userDetailsChecker::check).map((userDetails) -> {
|
||||
PreAuthenticatedAuthenticationToken result = new PreAuthenticatedAuthenticationToken(userDetails,
|
||||
authentication.getCredentials(), userDetails.getAuthorities());
|
||||
result.setDetails(authentication.getDetails());
|
||||
return result;
|
||||
});
|
||||
return Mono.just(authentication)
|
||||
.filter(this::supports)
|
||||
.map(Authentication::getName)
|
||||
.flatMap(this.userDetailsService::findByUsername)
|
||||
.switchIfEmpty(Mono.error(() -> new UsernameNotFoundException("User not found")))
|
||||
.doOnNext(this.userDetailsChecker::check)
|
||||
.map((userDetails) -> {
|
||||
PreAuthenticatedAuthenticationToken result = new PreAuthenticatedAuthenticationToken(userDetails,
|
||||
authentication.getCredentials(), userDetails.getAuthorities());
|
||||
result.setDetails(authentication.getDetails());
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
private boolean supports(Authentication authentication) {
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ public class RedirectServerAuthenticationEntryPoint implements ServerAuthenticat
|
||||
@Override
|
||||
public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException ex) {
|
||||
return this.requestCache.saveRequest(exchange)
|
||||
.then(this.redirectStrategy.sendRedirect(exchange, this.location));
|
||||
.then(this.redirectStrategy.sendRedirect(exchange, this.location));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-2
@@ -72,8 +72,9 @@ public class RedirectServerAuthenticationSuccessHandler implements ServerAuthent
|
||||
@Override
|
||||
public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {
|
||||
ServerWebExchange exchange = webFilterExchange.getExchange();
|
||||
return this.requestCache.getRedirectUri(exchange).defaultIfEmpty(this.location)
|
||||
.flatMap((location) -> this.redirectStrategy.sendRedirect(exchange, location));
|
||||
return this.requestCache.getRedirectUri(exchange)
|
||||
.defaultIfEmpty(this.location)
|
||||
.flatMap((location) -> this.redirectStrategy.sendRedirect(exchange, location));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-3
@@ -48,7 +48,7 @@ public final class ServerWebExchangeDelegatingReactiveAuthenticationManagerResol
|
||||
private final List<ServerWebExchangeMatcherEntry<ReactiveAuthenticationManager>> authenticationManagers;
|
||||
|
||||
private ReactiveAuthenticationManager defaultAuthenticationManager = (authentication) -> Mono
|
||||
.error(new AuthenticationServiceException("Cannot authenticate " + authentication));
|
||||
.error(new AuthenticationServiceException("Cannot authenticate " + authentication));
|
||||
|
||||
/**
|
||||
* Construct an
|
||||
@@ -78,8 +78,11 @@ public final class ServerWebExchangeDelegatingReactiveAuthenticationManagerResol
|
||||
*/
|
||||
@Override
|
||||
public Mono<ReactiveAuthenticationManager> resolve(ServerWebExchange exchange) {
|
||||
return Flux.fromIterable(this.authenticationManagers).filterWhen((entry) -> isMatch(exchange, entry)).next()
|
||||
.map(ServerWebExchangeMatcherEntry::getEntry).defaultIfEmpty(this.defaultAuthenticationManager);
|
||||
return Flux.fromIterable(this.authenticationManagers)
|
||||
.filterWhen((entry) -> isMatch(exchange, entry))
|
||||
.next()
|
||||
.map(ServerWebExchangeMatcherEntry::getEntry)
|
||||
.defaultIfEmpty(this.defaultAuthenticationManager);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+28
-25
@@ -158,13 +158,14 @@ public class SwitchUserWebFilter implements WebFilter {
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
final WebFilterExchange webFilterExchange = new WebFilterExchange(exchange, chain);
|
||||
return switchUser(webFilterExchange).switchIfEmpty(Mono.defer(() -> exitSwitchUser(webFilterExchange)))
|
||||
.switchIfEmpty(Mono.defer(() -> {
|
||||
this.logger.trace(
|
||||
LogMessage.format("Did not attempt to switch user since request did not match [%s] or [%s]",
|
||||
this.switchUserMatcher, this.exitUserMatcher));
|
||||
return chain.filter(exchange).then(Mono.empty());
|
||||
})).flatMap((authentication) -> onAuthenticationSuccess(authentication, webFilterExchange))
|
||||
.onErrorResume(SwitchUserAuthenticationException.class, (exception) -> Mono.empty());
|
||||
.switchIfEmpty(Mono.defer(() -> {
|
||||
this.logger
|
||||
.trace(LogMessage.format("Did not attempt to switch user since request did not match [%s] or [%s]",
|
||||
this.switchUserMatcher, this.exitUserMatcher));
|
||||
return chain.filter(exchange).then(Mono.empty());
|
||||
}))
|
||||
.flatMap((authentication) -> onAuthenticationSuccess(authentication, webFilterExchange))
|
||||
.onErrorResume(SwitchUserAuthenticationException.class, (exception) -> Mono.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,13 +178,15 @@ public class SwitchUserWebFilter implements WebFilter {
|
||||
*/
|
||||
protected Mono<Authentication> switchUser(WebFilterExchange webFilterExchange) {
|
||||
return this.switchUserMatcher.matches(webFilterExchange.getExchange())
|
||||
.filter(ServerWebExchangeMatcher.MatchResult::isMatch)
|
||||
.flatMap((matchResult) -> ReactiveSecurityContextHolder.getContext())
|
||||
.map(SecurityContext::getAuthentication).flatMap((currentAuthentication) -> {
|
||||
String username = getUsername(webFilterExchange.getExchange());
|
||||
return attemptSwitchUser(currentAuthentication, username);
|
||||
}).onErrorResume(AuthenticationException.class, (ex) -> onAuthenticationFailure(ex, webFilterExchange)
|
||||
.then(Mono.error(new SwitchUserAuthenticationException(ex))));
|
||||
.filter(ServerWebExchangeMatcher.MatchResult::isMatch)
|
||||
.flatMap((matchResult) -> ReactiveSecurityContextHolder.getContext())
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.flatMap((currentAuthentication) -> {
|
||||
String username = getUsername(webFilterExchange.getExchange());
|
||||
return attemptSwitchUser(currentAuthentication, username);
|
||||
})
|
||||
.onErrorResume(AuthenticationException.class, (ex) -> onAuthenticationFailure(ex, webFilterExchange)
|
||||
.then(Mono.error(new SwitchUserAuthenticationException(ex))));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,11 +199,11 @@ public class SwitchUserWebFilter implements WebFilter {
|
||||
*/
|
||||
protected Mono<Authentication> exitSwitchUser(WebFilterExchange webFilterExchange) {
|
||||
return this.exitUserMatcher.matches(webFilterExchange.getExchange())
|
||||
.filter(ServerWebExchangeMatcher.MatchResult::isMatch)
|
||||
.flatMap((matchResult) -> ReactiveSecurityContextHolder.getContext()
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.switchIfEmpty(Mono.error(this::noCurrentUserException)))
|
||||
.map(this::attemptExitUser);
|
||||
.filter(ServerWebExchangeMatcher.MatchResult::isMatch)
|
||||
.flatMap((matchResult) -> ReactiveSecurityContextHolder.getContext()
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.switchIfEmpty(Mono.error(this::noCurrentUserException)))
|
||||
.map(this::attemptExitUser);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,9 +220,9 @@ public class SwitchUserWebFilter implements WebFilter {
|
||||
Assert.notNull(userName, "The userName can not be null.");
|
||||
this.logger.debug(LogMessage.format("Attempting to switch to user [%s]", userName));
|
||||
return this.userDetailsService.findByUsername(userName)
|
||||
.switchIfEmpty(Mono.error(this::noTargetAuthenticationException))
|
||||
.doOnNext(this.userDetailsChecker::check)
|
||||
.map((userDetails) -> createSwitchUserToken(userDetails, currentAuthentication));
|
||||
.switchIfEmpty(Mono.error(this::noTargetAuthenticationException))
|
||||
.doOnNext(this.userDetailsChecker::check)
|
||||
.map((userDetails) -> createSwitchUserToken(userDetails, currentAuthentication));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -236,9 +239,9 @@ public class SwitchUserWebFilter implements WebFilter {
|
||||
ServerWebExchange exchange = webFilterExchange.getExchange();
|
||||
SecurityContextImpl securityContext = new SecurityContextImpl(authentication);
|
||||
return this.securityContextRepository.save(exchange, securityContext)
|
||||
.doOnSuccess((v) -> this.logger.debug(LogMessage.format("Switched user to %s", authentication)))
|
||||
.then(this.successHandler.onAuthenticationSuccess(webFilterExchange, authentication))
|
||||
.contextWrite(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext)));
|
||||
.doOnSuccess((v) -> this.logger.debug(LogMessage.format("Switched user to %s", authentication)))
|
||||
.then(this.successHandler.onAuthenticationSuccess(webFilterExchange, authentication))
|
||||
.contextWrite(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext)));
|
||||
}
|
||||
|
||||
private Mono<Void> onAuthenticationFailure(AuthenticationException exception, WebFilterExchange webFilterExchange) {
|
||||
|
||||
+3
-2
@@ -50,8 +50,9 @@ public class DelegatingServerLogoutHandler implements ServerLogoutHandler {
|
||||
|
||||
@Override
|
||||
public Mono<Void> logout(WebFilterExchange exchange, Authentication authentication) {
|
||||
return Flux.fromIterable(this.delegates).concatMap((delegate) -> delegate.logout(exchange, authentication))
|
||||
.then();
|
||||
return Flux.fromIterable(this.delegates)
|
||||
.concatMap((delegate) -> delegate.logout(exchange, authentication))
|
||||
.then();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-8
@@ -58,12 +58,15 @@ public class LogoutWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return this.requiresLogout.matches(exchange).filter((result) -> result.isMatch())
|
||||
.switchIfEmpty(chain.filter(exchange).then(Mono.empty())).map((result) -> exchange)
|
||||
.flatMap(this::flatMapAuthentication).flatMap((authentication) -> {
|
||||
WebFilterExchange webFilterExchange = new WebFilterExchange(exchange, chain);
|
||||
return logout(webFilterExchange, authentication);
|
||||
});
|
||||
return this.requiresLogout.matches(exchange)
|
||||
.filter((result) -> result.isMatch())
|
||||
.switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
|
||||
.map((result) -> exchange)
|
||||
.flatMap(this::flatMapAuthentication)
|
||||
.flatMap((authentication) -> {
|
||||
WebFilterExchange webFilterExchange = new WebFilterExchange(exchange, chain);
|
||||
return logout(webFilterExchange, authentication);
|
||||
});
|
||||
}
|
||||
|
||||
private Mono<Authentication> flatMapAuthentication(ServerWebExchange exchange) {
|
||||
@@ -73,8 +76,8 @@ public class LogoutWebFilter implements WebFilter {
|
||||
private Mono<Void> logout(WebFilterExchange webFilterExchange, Authentication authentication) {
|
||||
logger.debug(LogMessage.format("Logging out user '%s' and transferring to logout destination", authentication));
|
||||
return this.logoutHandler.logout(webFilterExchange, authentication)
|
||||
.then(this.logoutSuccessHandler.onLogoutSuccess(webFilterExchange, authentication))
|
||||
.contextWrite(ReactiveSecurityContextHolder.clearContext());
|
||||
.then(this.logoutSuccessHandler.onLogoutSuccess(webFilterExchange, authentication))
|
||||
.contextWrite(ReactiveSecurityContextHolder.clearContext());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+8
-7
@@ -46,13 +46,14 @@ public class AuthorizationWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return ReactiveSecurityContextHolder.getContext().filter((c) -> c.getAuthentication() != null)
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.as((authentication) -> this.authorizationManager.verify(authentication, exchange))
|
||||
.doOnSuccess((it) -> logger.debug("Authorization successful"))
|
||||
.doOnError(AccessDeniedException.class,
|
||||
(ex) -> logger.debug(LogMessage.format("Authorization failed: %s", ex.getMessage())))
|
||||
.switchIfEmpty(chain.filter(exchange));
|
||||
return ReactiveSecurityContextHolder.getContext()
|
||||
.filter((c) -> c.getAuthentication() != null)
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.as((authentication) -> this.authorizationManager.verify(authentication, exchange))
|
||||
.doOnSuccess((it) -> logger.debug("Authorization successful"))
|
||||
.doOnError(AccessDeniedException.class,
|
||||
(ex) -> logger.debug(LogMessage.format("Authorization failed: %s", ex.getMessage())))
|
||||
.switchIfEmpty(chain.filter(exchange));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-3
@@ -50,13 +50,19 @@ public final class DelegatingReactiveAuthorizationManager implements ReactiveAut
|
||||
|
||||
@Override
|
||||
public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, ServerWebExchange exchange) {
|
||||
return Flux.fromIterable(this.mappings).concatMap((mapping) -> mapping.getMatcher().matches(exchange)
|
||||
.filter(MatchResult::isMatch).map(MatchResult::getVariables).flatMap((variables) -> {
|
||||
return Flux.fromIterable(this.mappings)
|
||||
.concatMap((mapping) -> mapping.getMatcher()
|
||||
.matches(exchange)
|
||||
.filter(MatchResult::isMatch)
|
||||
.map(MatchResult::getVariables)
|
||||
.flatMap((variables) -> {
|
||||
logger.debug(LogMessage.of(() -> "Checking authorization on '"
|
||||
+ exchange.getRequest().getPath().pathWithinApplication() + "' using "
|
||||
+ mapping.getEntry()));
|
||||
return mapping.getEntry().check(authentication, new AuthorizationContext(exchange, variables));
|
||||
})).next().defaultIfEmpty(new AuthorizationDecision(false));
|
||||
}))
|
||||
.next()
|
||||
.defaultIfEmpty(new AuthorizationDecision(false));
|
||||
}
|
||||
|
||||
public static DelegatingReactiveAuthorizationManager.Builder builder() {
|
||||
|
||||
+6
-4
@@ -49,13 +49,15 @@ public class ExceptionTranslationWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return chain.filter(exchange).onErrorResume(AccessDeniedException.class, (denied) -> exchange.getPrincipal()
|
||||
return chain.filter(exchange)
|
||||
.onErrorResume(AccessDeniedException.class, (denied) -> exchange.getPrincipal()
|
||||
.filter((principal) -> (!(principal instanceof Authentication) || (principal instanceof Authentication
|
||||
&& !(this.authenticationTrustResolver.isAnonymous((Authentication) principal)))))
|
||||
.switchIfEmpty(commenceAuthentication(exchange,
|
||||
new InsufficientAuthenticationException(
|
||||
"Full authentication is required to access this resource")))
|
||||
.flatMap((principal) -> this.accessDeniedHandler.handle(exchange, denied)).then());
|
||||
.flatMap((principal) -> this.accessDeniedHandler.handle(exchange, denied))
|
||||
.then());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,8 +94,8 @@ public class ExceptionTranslationWebFilter implements WebFilter {
|
||||
|
||||
private <T> Mono<T> commenceAuthentication(ServerWebExchange exchange, AuthenticationException denied) {
|
||||
return this.authenticationEntryPoint
|
||||
.commence(exchange, new AuthenticationCredentialsNotFoundException("Not Authenticated", denied))
|
||||
.then(Mono.empty());
|
||||
.commence(exchange, new AuthenticationCredentialsNotFoundException("Not Authenticated", denied))
|
||||
.then(Mono.empty());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -41,8 +41,9 @@ public final class IpAddressReactiveAuthorizationManager implements ReactiveAuth
|
||||
|
||||
@Override
|
||||
public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, AuthorizationContext context) {
|
||||
return Mono.just(context.getExchange()).flatMap(this.ipAddressExchangeMatcher::matches)
|
||||
.map((matchResult) -> new AuthorizationDecision(matchResult.isMatch()));
|
||||
return Mono.just(context.getExchange())
|
||||
.flatMap(this.ipAddressExchangeMatcher::matches)
|
||||
.map((matchResult) -> new AuthorizationDecision(matchResult.isMatch()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-3
@@ -69,9 +69,12 @@ public class ServerWebExchangeDelegatingServerAccessDeniedHandler implements Ser
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) {
|
||||
return Flux.fromIterable(this.handlers).filterWhen((entry) -> isMatch(exchange, entry)).next()
|
||||
.map(DelegateEntry::getAccessDeniedHandler).defaultIfEmpty(this.defaultHandler)
|
||||
.flatMap((handler) -> handler.handle(exchange, denied));
|
||||
return Flux.fromIterable(this.handlers)
|
||||
.filterWhen((entry) -> isMatch(exchange, entry))
|
||||
.next()
|
||||
.map(DelegateEntry::getAccessDeniedHandler)
|
||||
.defaultIfEmpty(this.defaultHandler)
|
||||
.flatMap((handler) -> handler.handle(exchange, denied));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+5
-4
@@ -44,13 +44,14 @@ public class ReactorContextWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return chain.filter(exchange).contextWrite(
|
||||
(context) -> context.hasKey(SecurityContext.class) ? context : withSecurityContext(context, exchange));
|
||||
return chain.filter(exchange)
|
||||
.contextWrite((context) -> context.hasKey(SecurityContext.class) ? context
|
||||
: withSecurityContext(context, exchange));
|
||||
}
|
||||
|
||||
private Context withSecurityContext(Context mainContext, ServerWebExchange exchange) {
|
||||
return mainContext.putAll(
|
||||
this.repository.load(exchange).as(ReactiveSecurityContextHolder::withSecurityContext).readOnly());
|
||||
return mainContext
|
||||
.putAll(this.repository.load(exchange).as(ReactiveSecurityContextHolder::withSecurityContext).readOnly());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -118,11 +118,13 @@ public class CsrfWebFilter implements WebFilter {
|
||||
if (Boolean.TRUE.equals(exchange.getAttribute(SHOULD_NOT_FILTER))) {
|
||||
return chain.filter(exchange).then(Mono.empty());
|
||||
}
|
||||
return this.requireCsrfProtectionMatcher.matches(exchange).filter(MatchResult::isMatch)
|
||||
.filter((matchResult) -> !exchange.getAttributes().containsKey(CsrfToken.class.getName()))
|
||||
.flatMap((m) -> validateToken(exchange)).flatMap((m) -> continueFilterChain(exchange, chain))
|
||||
.switchIfEmpty(continueFilterChain(exchange, chain).then(Mono.empty()))
|
||||
.onErrorResume(CsrfException.class, (ex) -> this.accessDeniedHandler.handle(exchange, ex));
|
||||
return this.requireCsrfProtectionMatcher.matches(exchange)
|
||||
.filter(MatchResult::isMatch)
|
||||
.filter((matchResult) -> !exchange.getAttributes().containsKey(CsrfToken.class.getName()))
|
||||
.flatMap((m) -> validateToken(exchange))
|
||||
.flatMap((m) -> continueFilterChain(exchange, chain))
|
||||
.switchIfEmpty(continueFilterChain(exchange, chain).then(Mono.empty()))
|
||||
.onErrorResume(CsrfException.class, (ex) -> this.accessDeniedHandler.handle(exchange, ex));
|
||||
}
|
||||
|
||||
public static void skipExchange(ServerWebExchange exchange) {
|
||||
@@ -131,15 +133,15 @@ public class CsrfWebFilter implements WebFilter {
|
||||
|
||||
private Mono<Void> validateToken(ServerWebExchange exchange) {
|
||||
return this.csrfTokenRepository.loadToken(exchange)
|
||||
.switchIfEmpty(
|
||||
Mono.defer(() -> Mono.error(new CsrfException("An expected CSRF token cannot be found"))))
|
||||
.filterWhen((expected) -> containsValidCsrfToken(exchange, expected))
|
||||
.switchIfEmpty(Mono.defer(() -> Mono.error(new CsrfException("Invalid CSRF Token")))).then();
|
||||
.switchIfEmpty(Mono.defer(() -> Mono.error(new CsrfException("An expected CSRF token cannot be found"))))
|
||||
.filterWhen((expected) -> containsValidCsrfToken(exchange, expected))
|
||||
.switchIfEmpty(Mono.defer(() -> Mono.error(new CsrfException("Invalid CSRF Token"))))
|
||||
.then();
|
||||
}
|
||||
|
||||
private Mono<Boolean> containsValidCsrfToken(ServerWebExchange exchange, CsrfToken expected) {
|
||||
return this.requestHandler.resolveCsrfTokenValue(exchange, expected)
|
||||
.map((actual) -> equalsConstantTime(actual, expected.getToken()));
|
||||
.map((actual) -> equalsConstantTime(actual, expected.getToken()));
|
||||
}
|
||||
|
||||
private Mono<Void> continueFilterChain(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
@@ -175,7 +177,8 @@ public class CsrfWebFilter implements WebFilter {
|
||||
|
||||
private Mono<CsrfToken> generateToken(ServerWebExchange exchange) {
|
||||
return this.csrfTokenRepository.generateToken(exchange)
|
||||
.delayUntil((token) -> this.csrfTokenRepository.saveToken(exchange, token)).cache();
|
||||
.delayUntil((token) -> this.csrfTokenRepository.saveToken(exchange, token))
|
||||
.cache();
|
||||
}
|
||||
|
||||
private static class DefaultRequireCsrfProtectionMatcher implements ServerWebExchangeMatcher {
|
||||
@@ -185,9 +188,11 @@ public class CsrfWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<MatchResult> matches(ServerWebExchange exchange) {
|
||||
return Mono.just(exchange.getRequest()).flatMap((r) -> Mono.justOrEmpty(r.getMethod()))
|
||||
.filter(ALLOWED_METHODS::contains).flatMap((m) -> MatchResult.notMatch())
|
||||
.switchIfEmpty(MatchResult.match());
|
||||
return Mono.just(exchange.getRequest())
|
||||
.flatMap((r) -> Mono.justOrEmpty(r.getMethod()))
|
||||
.filter(ALLOWED_METHODS::contains)
|
||||
.flatMap((m) -> MatchResult.notMatch())
|
||||
.switchIfEmpty(MatchResult.match());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-3
@@ -47,7 +47,7 @@ public class ServerCsrfTokenRequestAttributeHandler implements ServerCsrfTokenRe
|
||||
@Override
|
||||
public Mono<String> resolveCsrfTokenValue(ServerWebExchange exchange, CsrfToken csrfToken) {
|
||||
return ServerCsrfTokenRequestHandler.super.resolveCsrfTokenValue(exchange, csrfToken)
|
||||
.switchIfEmpty(tokenFromMultipartData(exchange, csrfToken));
|
||||
.switchIfEmpty(tokenFromMultipartData(exchange, csrfToken));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,8 +70,10 @@ public class ServerCsrfTokenRequestAttributeHandler implements ServerCsrfTokenRe
|
||||
if (!MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)) {
|
||||
return Mono.empty();
|
||||
}
|
||||
return exchange.getMultipartData().map((d) -> d.getFirst(expected.getParameterName())).cast(FormFieldPart.class)
|
||||
.map(FormFieldPart::value);
|
||||
return exchange.getMultipartData()
|
||||
.map((d) -> d.getFirst(expected.getParameterName()))
|
||||
.cast(FormFieldPart.class)
|
||||
.map(FormFieldPart::value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -46,9 +46,9 @@ public interface ServerCsrfTokenRequestHandler extends ServerCsrfTokenRequestRes
|
||||
default Mono<String> resolveCsrfTokenValue(ServerWebExchange exchange, CsrfToken csrfToken) {
|
||||
Assert.notNull(exchange, "exchange cannot be null");
|
||||
Assert.notNull(csrfToken, "csrfToken cannot be null");
|
||||
return exchange.getFormData().flatMap((data) -> Mono.justOrEmpty(data.getFirst(csrfToken.getParameterName())))
|
||||
.switchIfEmpty(
|
||||
Mono.justOrEmpty(exchange.getRequest().getHeaders().getFirst(csrfToken.getHeaderName())));
|
||||
return exchange.getFormData()
|
||||
.flatMap((data) -> Mono.justOrEmpty(data.getFirst(csrfToken.getParameterName())))
|
||||
.switchIfEmpty(Mono.justOrEmpty(exchange.getRequest().getHeaders().getFirst(csrfToken.getHeaderName())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-5
@@ -41,7 +41,7 @@ public class WebSessionServerCsrfTokenRepository implements ServerCsrfTokenRepos
|
||||
private static final String DEFAULT_CSRF_HEADER_NAME = "X-CSRF-TOKEN";
|
||||
|
||||
private static final String DEFAULT_CSRF_TOKEN_ATTR_NAME = WebSessionServerCsrfTokenRepository.class.getName()
|
||||
.concat(".CSRF_TOKEN");
|
||||
.concat(".CSRF_TOKEN");
|
||||
|
||||
private String parameterName = DEFAULT_CSRF_PARAMETER_NAME;
|
||||
|
||||
@@ -56,8 +56,9 @@ public class WebSessionServerCsrfTokenRepository implements ServerCsrfTokenRepos
|
||||
|
||||
@Override
|
||||
public Mono<Void> saveToken(ServerWebExchange exchange, CsrfToken token) {
|
||||
return exchange.getSession().doOnNext((session) -> putToken(session.getAttributes(), token))
|
||||
.flatMap((session) -> session.changeSessionId());
|
||||
return exchange.getSession()
|
||||
.doOnNext((session) -> putToken(session.getAttributes(), token))
|
||||
.flatMap((session) -> session.changeSessionId());
|
||||
}
|
||||
|
||||
private void putToken(Map<String, Object> attributes, CsrfToken token) {
|
||||
@@ -71,8 +72,9 @@ public class WebSessionServerCsrfTokenRepository implements ServerCsrfTokenRepos
|
||||
|
||||
@Override
|
||||
public Mono<CsrfToken> loadToken(ServerWebExchange exchange) {
|
||||
return exchange.getSession().filter((session) -> session.getAttributes().containsKey(this.sessionAttributeName))
|
||||
.map((session) -> session.getAttribute(this.sessionAttributeName));
|
||||
return exchange.getSession()
|
||||
.filter((session) -> session.getAttributes().containsKey(this.sessionAttributeName))
|
||||
.map((session) -> session.getAttribute(this.sessionAttributeName));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-4
@@ -52,16 +52,18 @@ public final class XorServerCsrfTokenRequestAttributeHandler extends ServerCsrfT
|
||||
public void handle(ServerWebExchange exchange, Mono<CsrfToken> csrfToken) {
|
||||
Assert.notNull(exchange, "exchange cannot be null");
|
||||
Assert.notNull(csrfToken, "csrfToken cannot be null");
|
||||
Mono<CsrfToken> updatedCsrfToken = csrfToken.map((token) -> new DefaultCsrfToken(token.getHeaderName(),
|
||||
token.getParameterName(), createXoredCsrfToken(this.secureRandom, token.getToken())))
|
||||
.cast(CsrfToken.class).cache();
|
||||
Mono<CsrfToken> updatedCsrfToken = csrfToken
|
||||
.map((token) -> new DefaultCsrfToken(token.getHeaderName(), token.getParameterName(),
|
||||
createXoredCsrfToken(this.secureRandom, token.getToken())))
|
||||
.cast(CsrfToken.class)
|
||||
.cache();
|
||||
super.handle(exchange, updatedCsrfToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<String> resolveCsrfTokenValue(ServerWebExchange exchange, CsrfToken csrfToken) {
|
||||
return super.resolveCsrfTokenValue(exchange, csrfToken)
|
||||
.flatMap((actualToken) -> Mono.justOrEmpty(getTokenValue(actualToken, csrfToken.getToken())));
|
||||
.flatMap((actualToken) -> Mono.justOrEmpty(getTokenValue(actualToken, csrfToken.getToken())));
|
||||
}
|
||||
|
||||
private static String getTokenValue(String actualToken, String token) {
|
||||
|
||||
+4
-3
@@ -55,9 +55,10 @@ public class CacheControlServerHttpHeadersWriter implements ServerHttpHeadersWri
|
||||
* The delegate to write all the cache control related headers
|
||||
*/
|
||||
private static final ServerHttpHeadersWriter CACHE_HEADERS = StaticServerHttpHeadersWriter.builder()
|
||||
.header(HttpHeaders.CACHE_CONTROL, CacheControlServerHttpHeadersWriter.CACHE_CONTRTOL_VALUE)
|
||||
.header(HttpHeaders.PRAGMA, CacheControlServerHttpHeadersWriter.PRAGMA_VALUE)
|
||||
.header(HttpHeaders.EXPIRES, CacheControlServerHttpHeadersWriter.EXPIRES_VALUE).build();
|
||||
.header(HttpHeaders.CACHE_CONTROL, CacheControlServerHttpHeadersWriter.CACHE_CONTRTOL_VALUE)
|
||||
.header(HttpHeaders.PRAGMA, CacheControlServerHttpHeadersWriter.PRAGMA_VALUE)
|
||||
.header(HttpHeaders.EXPIRES, CacheControlServerHttpHeadersWriter.EXPIRES_VALUE)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public Mono<Void> writeHttpHeaders(ServerWebExchange exchange) {
|
||||
|
||||
+2
-1
@@ -50,7 +50,8 @@ public final class ClearSiteDataServerHttpHeadersWriter implements ServerHttpHea
|
||||
public ClearSiteDataServerHttpHeadersWriter(Directive... directives) {
|
||||
Assert.notEmpty(directives, "directives cannot be empty or null");
|
||||
this.headerWriterDelegate = StaticServerHttpHeadersWriter.builder()
|
||||
.header(CLEAR_SITE_DATA_HEADER, transformToHeaderValue(directives)).build();
|
||||
.header(CLEAR_SITE_DATA_HEADER, transformToHeaderValue(directives))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-1
@@ -36,7 +36,8 @@ public class ContentTypeOptionsServerHttpHeadersWriter implements ServerHttpHead
|
||||
* The delegate to write all the cache control related headers
|
||||
*/
|
||||
private static final ServerHttpHeadersWriter CONTENT_TYPE_HEADERS = StaticServerHttpHeadersWriter.builder()
|
||||
.header(X_CONTENT_OPTIONS, NOSNIFF).build();
|
||||
.header(X_CONTENT_OPTIONS, NOSNIFF)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public Mono<Void> writeHttpHeaders(ServerWebExchange exchange) {
|
||||
|
||||
+4
-2
@@ -62,8 +62,10 @@ public final class ServerWebExchangeDelegatingServerHttpHeadersWriter implements
|
||||
|
||||
@Override
|
||||
public Mono<Void> writeHttpHeaders(ServerWebExchange exchange) {
|
||||
return this.headersWriter.getMatcher().matches(exchange).filter(ServerWebExchangeMatcher.MatchResult::isMatch)
|
||||
.flatMap((matchResult) -> this.headersWriter.getEntry().writeHttpHeaders(exchange));
|
||||
return this.headersWriter.getMatcher()
|
||||
.matches(exchange)
|
||||
.filter(ServerWebExchangeMatcher.MatchResult::isMatch)
|
||||
.flatMap((matchResult) -> this.headersWriter.getEntry().writeHttpHeaders(exchange));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -36,7 +36,8 @@ public class XContentTypeOptionsServerHttpHeadersWriter implements ServerHttpHea
|
||||
* The delegate to write all the cache control related headers
|
||||
*/
|
||||
private static final ServerHttpHeadersWriter CONTENT_TYPE_HEADERS = StaticServerHttpHeadersWriter.builder()
|
||||
.header(X_CONTENT_OPTIONS, NOSNIFF).build();
|
||||
.header(X_CONTENT_OPTIONS, NOSNIFF)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public Mono<Void> writeHttpHeaders(ServerWebExchange exchange) {
|
||||
|
||||
+26
-14
@@ -72,27 +72,35 @@ public class CookieServerRequestCache implements ServerRequestCache {
|
||||
|
||||
@Override
|
||||
public Mono<Void> saveRequest(ServerWebExchange exchange) {
|
||||
return this.saveRequestMatcher.matches(exchange).filter((m) -> m.isMatch()).map((m) -> exchange.getResponse())
|
||||
.map(ServerHttpResponse::getCookies).doOnNext((cookies) -> {
|
||||
ResponseCookie redirectUriCookie = createRedirectUriCookie(exchange.getRequest());
|
||||
cookies.add(REDIRECT_URI_COOKIE_NAME, redirectUriCookie);
|
||||
logger.debug(LogMessage.format("Request added to Cookie: %s", redirectUriCookie));
|
||||
}).then();
|
||||
return this.saveRequestMatcher.matches(exchange)
|
||||
.filter((m) -> m.isMatch())
|
||||
.map((m) -> exchange.getResponse())
|
||||
.map(ServerHttpResponse::getCookies)
|
||||
.doOnNext((cookies) -> {
|
||||
ResponseCookie redirectUriCookie = createRedirectUriCookie(exchange.getRequest());
|
||||
cookies.add(REDIRECT_URI_COOKIE_NAME, redirectUriCookie);
|
||||
logger.debug(LogMessage.format("Request added to Cookie: %s", redirectUriCookie));
|
||||
})
|
||||
.then();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<URI> getRedirectUri(ServerWebExchange exchange) {
|
||||
MultiValueMap<String, HttpCookie> cookieMap = exchange.getRequest().getCookies();
|
||||
return Mono.justOrEmpty(cookieMap.getFirst(REDIRECT_URI_COOKIE_NAME)).map(HttpCookie::getValue)
|
||||
.map(CookieServerRequestCache::decodeCookie)
|
||||
.onErrorResume(IllegalArgumentException.class, (ex) -> Mono.empty()).map(URI::create);
|
||||
return Mono.justOrEmpty(cookieMap.getFirst(REDIRECT_URI_COOKIE_NAME))
|
||||
.map(HttpCookie::getValue)
|
||||
.map(CookieServerRequestCache::decodeCookie)
|
||||
.onErrorResume(IllegalArgumentException.class, (ex) -> Mono.empty())
|
||||
.map(URI::create);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ServerHttpRequest> removeMatchingRequest(ServerWebExchange exchange) {
|
||||
return Mono.just(exchange.getResponse()).map(ServerHttpResponse::getCookies).doOnNext(
|
||||
(cookies) -> cookies.add(REDIRECT_URI_COOKIE_NAME, invalidateRedirectUriCookie(exchange.getRequest())))
|
||||
.thenReturn(exchange.getRequest());
|
||||
return Mono.just(exchange.getResponse())
|
||||
.map(ServerHttpResponse::getCookies)
|
||||
.doOnNext((cookies) -> cookies.add(REDIRECT_URI_COOKIE_NAME,
|
||||
invalidateRedirectUriCookie(exchange.getRequest())))
|
||||
.thenReturn(exchange.getRequest());
|
||||
}
|
||||
|
||||
private static ResponseCookie createRedirectUriCookie(ServerHttpRequest request) {
|
||||
@@ -108,8 +116,12 @@ public class CookieServerRequestCache implements ServerRequestCache {
|
||||
|
||||
private static ResponseCookie createResponseCookie(ServerHttpRequest request, String cookieValue, Duration age) {
|
||||
return ResponseCookie.from(REDIRECT_URI_COOKIE_NAME, cookieValue)
|
||||
.path(request.getPath().contextPath().value() + "/").maxAge(age).httpOnly(true)
|
||||
.secure("https".equalsIgnoreCase(request.getURI().getScheme())).sameSite("Lax").build();
|
||||
.path(request.getPath().contextPath().value() + "/")
|
||||
.maxAge(age)
|
||||
.httpOnly(true)
|
||||
.secure("https".equalsIgnoreCase(request.getURI().getScheme()))
|
||||
.sameSite("Lax")
|
||||
.build();
|
||||
}
|
||||
|
||||
private static String encodeCookie(String cookieValue) {
|
||||
|
||||
+4
-2
@@ -35,8 +35,10 @@ public class ServerRequestCacheWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return this.requestCache.removeMatchingRequest(exchange).map((r) -> exchange.mutate().request(r).build())
|
||||
.defaultIfEmpty(exchange).flatMap((e) -> chain.filter(e));
|
||||
return this.requestCache.removeMatchingRequest(exchange)
|
||||
.map((r) -> exchange.mutate().request(r).build())
|
||||
.defaultIfEmpty(exchange)
|
||||
.flatMap((e) -> chain.filter(e));
|
||||
}
|
||||
|
||||
public void setRequestCache(ServerRequestCache requestCache) {
|
||||
|
||||
+12
-8
@@ -73,19 +73,23 @@ public class WebSessionServerRequestCache implements ServerRequestCache {
|
||||
|
||||
@Override
|
||||
public Mono<Void> saveRequest(ServerWebExchange exchange) {
|
||||
return this.saveRequestMatcher.matches(exchange).filter(MatchResult::isMatch)
|
||||
.flatMap((m) -> exchange.getSession()).map(WebSession::getAttributes).doOnNext((attrs) -> {
|
||||
String requestPath = pathInApplication(exchange.getRequest());
|
||||
attrs.put(this.sessionAttrName, requestPath);
|
||||
logger.debug(LogMessage.format("Request added to WebSession: '%s'", requestPath));
|
||||
}).then();
|
||||
return this.saveRequestMatcher.matches(exchange)
|
||||
.filter(MatchResult::isMatch)
|
||||
.flatMap((m) -> exchange.getSession())
|
||||
.map(WebSession::getAttributes)
|
||||
.doOnNext((attrs) -> {
|
||||
String requestPath = pathInApplication(exchange.getRequest());
|
||||
attrs.put(this.sessionAttrName, requestPath);
|
||||
logger.debug(LogMessage.format("Request added to WebSession: '%s'", requestPath));
|
||||
})
|
||||
.then();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<URI> getRedirectUri(ServerWebExchange exchange) {
|
||||
return exchange.getSession()
|
||||
.flatMap((session) -> Mono.justOrEmpty(session.<String>getAttribute(this.sessionAttrName)))
|
||||
.map(this::createRedirectUri);
|
||||
.flatMap((session) -> Mono.justOrEmpty(session.<String>getAttribute(this.sessionAttrName)))
|
||||
.map(this::createRedirectUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+7
-4
@@ -53,10 +53,13 @@ public final class HttpsRedirectWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return Mono.just(exchange).filter(this::isInsecure).flatMap(this.requiresHttpsRedirectMatcher::matches)
|
||||
.filter((matchResult) -> matchResult.isMatch()).switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
|
||||
.map((matchResult) -> createRedirectUri(exchange))
|
||||
.flatMap((uri) -> this.redirectStrategy.sendRedirect(exchange, uri));
|
||||
return Mono.just(exchange)
|
||||
.filter(this::isInsecure)
|
||||
.flatMap(this.requiresHttpsRedirectMatcher::matches)
|
||||
.filter((matchResult) -> matchResult.isMatch())
|
||||
.switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
|
||||
.map((matchResult) -> createRedirectUri(exchange))
|
||||
.flatMap((uri) -> this.redirectStrategy.sendRedirect(exchange, uri));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+5
-3
@@ -63,8 +63,10 @@ public class LoginPageGeneratingWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return this.matcher.matches(exchange).filter(ServerWebExchangeMatcher.MatchResult::isMatch)
|
||||
.switchIfEmpty(chain.filter(exchange).then(Mono.empty())).flatMap((matchResult) -> render(exchange));
|
||||
return this.matcher.matches(exchange)
|
||||
.filter(ServerWebExchangeMatcher.MatchResult::isMatch)
|
||||
.switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
|
||||
.flatMap((matchResult) -> render(exchange));
|
||||
}
|
||||
|
||||
private Mono<Void> render(ServerWebExchange exchange) {
|
||||
@@ -148,7 +150,7 @@ public class LoginPageGeneratingWebFilter implements WebFilter {
|
||||
sb.append(createError(isError));
|
||||
sb.append("<table class=\"table table-striped\">\n");
|
||||
for (Map.Entry<String, String> clientAuthenticationUrlToClientName : oauth2AuthenticationUrlToClientName
|
||||
.entrySet()) {
|
||||
.entrySet()) {
|
||||
sb.append(" <tr><td>");
|
||||
String url = clientAuthenticationUrlToClientName.getKey();
|
||||
sb.append("<a href=\"").append(contextPath).append(url).append("\">");
|
||||
|
||||
+4
-2
@@ -45,8 +45,10 @@ public class LogoutPageGeneratingWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return this.matcher.matches(exchange).filter(ServerWebExchangeMatcher.MatchResult::isMatch)
|
||||
.switchIfEmpty(chain.filter(exchange).then(Mono.empty())).flatMap((matchResult) -> render(exchange));
|
||||
return this.matcher.matches(exchange)
|
||||
.filter(ServerWebExchangeMatcher.MatchResult::isMatch)
|
||||
.switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
|
||||
.flatMap((matchResult) -> render(exchange));
|
||||
}
|
||||
|
||||
private Mono<Void> render(ServerWebExchange exchange) {
|
||||
|
||||
+7
-6
@@ -58,12 +58,13 @@ public class AndServerWebExchangeMatcher implements ServerWebExchangeMatcher {
|
||||
return Mono.defer(() -> {
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
return Flux.fromIterable(this.matchers)
|
||||
.doOnNext((matcher) -> logger.debug(LogMessage.format("Trying to match using %s", matcher)))
|
||||
.flatMap((matcher) -> matcher.matches(exchange))
|
||||
.doOnNext((matchResult) -> variables.putAll(matchResult.getVariables())).all(MatchResult::isMatch)
|
||||
.flatMap((allMatch) -> allMatch ? MatchResult.match(variables) : MatchResult.notMatch())
|
||||
.doOnNext((matchResult) -> logger
|
||||
.debug(matchResult.isMatch() ? "All requestMatchers returned true" : "Did not match"));
|
||||
.doOnNext((matcher) -> logger.debug(LogMessage.format("Trying to match using %s", matcher)))
|
||||
.flatMap((matcher) -> matcher.matches(exchange))
|
||||
.doOnNext((matchResult) -> variables.putAll(matchResult.getVariables()))
|
||||
.all(MatchResult::isMatch)
|
||||
.flatMap((allMatch) -> allMatch ? MatchResult.match(variables) : MatchResult.notMatch())
|
||||
.doOnNext((matchResult) -> logger
|
||||
.debug(matchResult.isMatch() ? "All requestMatchers returned true" : "Did not match"));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -45,8 +45,9 @@ public class NegatedServerWebExchangeMatcher implements ServerWebExchangeMatcher
|
||||
|
||||
@Override
|
||||
public Mono<MatchResult> matches(ServerWebExchange exchange) {
|
||||
return this.matcher.matches(exchange).flatMap(this::negate)
|
||||
.doOnNext((matchResult) -> logger.debug(LogMessage.format("matches = %s", matchResult.isMatch())));
|
||||
return this.matcher.matches(exchange)
|
||||
.flatMap(this::negate)
|
||||
.doOnNext((matchResult) -> logger.debug(LogMessage.format("matches = %s", matchResult.isMatch())));
|
||||
}
|
||||
|
||||
private Mono<MatchResult> negate(MatchResult matchResult) {
|
||||
|
||||
+6
-4
@@ -54,10 +54,12 @@ public class OrServerWebExchangeMatcher implements ServerWebExchangeMatcher {
|
||||
@Override
|
||||
public Mono<MatchResult> matches(ServerWebExchange exchange) {
|
||||
return Flux.fromIterable(this.matchers)
|
||||
.doOnNext((matcher) -> logger.debug(LogMessage.format("Trying to match using %s", matcher)))
|
||||
.flatMap((matcher) -> matcher.matches(exchange)).filter(MatchResult::isMatch).next()
|
||||
.switchIfEmpty(MatchResult.notMatch())
|
||||
.doOnNext((matchResult) -> logger.debug(matchResult.isMatch() ? "matched" : "No matches found"));
|
||||
.doOnNext((matcher) -> logger.debug(LogMessage.format("Trying to match using %s", matcher)))
|
||||
.flatMap((matcher) -> matcher.matches(exchange))
|
||||
.filter(MatchResult::isMatch)
|
||||
.next()
|
||||
.switchIfEmpty(MatchResult.notMatch())
|
||||
.doOnNext((matchResult) -> logger.debug(matchResult.isMatch() ? "matched" : "No matches found"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -96,8 +96,8 @@ public final class PathPatternParserServerWebExchangeMatcher implements ServerWe
|
||||
Map<String, String> pathVariables = this.pattern.matchAndExtract(path).getUriVariables();
|
||||
Map<String, Object> variables = new HashMap<>(pathVariables);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"Checking match of request : '" + path + "'; against '" + this.pattern.getPatternString() + "'");
|
||||
logger
|
||||
.debug("Checking match of request : '" + path + "'; against '" + this.pattern.getPatternString() + "'");
|
||||
}
|
||||
return MatchResult.match(variables);
|
||||
}
|
||||
|
||||
+1
-1
@@ -183,7 +183,7 @@ public class MvcRequestMatcher implements RequestMatcher, RequestVariablesExtrac
|
||||
String lookupPath = this.pathHelper.getLookupPathForRequest(request);
|
||||
if (matches(lookupPath)) {
|
||||
Map<String, String> variables = this.pathMatcher
|
||||
.extractUriTemplateVariables(MvcRequestMatcher.this.pattern, lookupPath);
|
||||
.extractUriTemplateVariables(MvcRequestMatcher.this.pattern, lookupPath);
|
||||
return MatchResult.match(variables);
|
||||
}
|
||||
return MatchResult.notMatch();
|
||||
|
||||
+7
-7
@@ -79,7 +79,7 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private final String rolePrefix;
|
||||
|
||||
@@ -238,14 +238,14 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
|
||||
}
|
||||
AuthenticationManager authManager = HttpServlet3RequestFactory.this.authenticationManager;
|
||||
if (authManager == null) {
|
||||
HttpServlet3RequestFactory.this.logger.debug(
|
||||
"authenticationManager is null, so allowing original HttpServletRequest to handle login");
|
||||
HttpServlet3RequestFactory.this.logger
|
||||
.debug("authenticationManager is null, so allowing original HttpServletRequest to handle login");
|
||||
super.login(username, password);
|
||||
return;
|
||||
}
|
||||
Authentication authentication = getAuthentication(authManager, username, password);
|
||||
SecurityContext context = HttpServlet3RequestFactory.this.securityContextHolderStrategy
|
||||
.createEmptyContext();
|
||||
.createEmptyContext();
|
||||
context.setAuthentication(authentication);
|
||||
HttpServlet3RequestFactory.this.securityContextHolderStrategy.setContext(context);
|
||||
HttpServlet3RequestFactory.this.securityContextRepository.saveContext(context, this, this.response);
|
||||
@@ -255,7 +255,7 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
|
||||
throws ServletException {
|
||||
try {
|
||||
UsernamePasswordAuthenticationToken authentication = UsernamePasswordAuthenticationToken
|
||||
.unauthenticated(username, password);
|
||||
.unauthenticated(username, password);
|
||||
Object details = HttpServlet3RequestFactory.this.authenticationDetailsSource.buildDetails(this);
|
||||
authentication.setDetails(details);
|
||||
return authManager.authenticate(authentication);
|
||||
@@ -271,12 +271,12 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
|
||||
List<LogoutHandler> handlers = HttpServlet3RequestFactory.this.logoutHandlers;
|
||||
if (CollectionUtils.isEmpty(handlers)) {
|
||||
HttpServlet3RequestFactory.this.logger
|
||||
.debug("logoutHandlers is null, so allowing original HttpServletRequest to handle logout");
|
||||
.debug("logoutHandlers is null, so allowing original HttpServletRequest to handle logout");
|
||||
super.logout();
|
||||
return;
|
||||
}
|
||||
Authentication authentication = HttpServlet3RequestFactory.this.securityContextHolderStrategy.getContext()
|
||||
.getAuthentication();
|
||||
.getAuthentication();
|
||||
for (LogoutHandler handler : handlers) {
|
||||
handler.logout(this, this.response, authentication);
|
||||
}
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private String rolePrefix = "ROLE_";
|
||||
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ import org.springframework.util.Assert;
|
||||
public class SecurityContextHolderAwareRequestWrapper extends HttpServletRequestWrapper {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private final AuthenticationTrustResolver trustResolver;
|
||||
|
||||
|
||||
+6
-5
@@ -69,7 +69,7 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
public class ConcurrentSessionFilter extends GenericFilterBean {
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private final SessionRegistry sessionRegistry;
|
||||
|
||||
@@ -138,10 +138,10 @@ public class ConcurrentSessionFilter extends GenericFilterBean {
|
||||
if (info.isExpired()) {
|
||||
// Expired - abort processing
|
||||
this.logger.debug(LogMessage
|
||||
.of(() -> "Requested session ID " + request.getRequestedSessionId() + " has expired."));
|
||||
.of(() -> "Requested session ID " + request.getRequestedSessionId() + " has expired."));
|
||||
doLogout(request, response);
|
||||
this.sessionInformationExpiredStrategy
|
||||
.onExpiredSessionDetected(new SessionInformationExpiredEvent(info, request, response));
|
||||
.onExpiredSessionDetected(new SessionInformationExpiredEvent(info, request, response));
|
||||
return;
|
||||
}
|
||||
// Non-expired - update last request date/time
|
||||
@@ -221,8 +221,9 @@ public class ConcurrentSessionFilter extends GenericFilterBean {
|
||||
@Override
|
||||
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException {
|
||||
HttpServletResponse response = event.getResponse();
|
||||
response.getWriter().print("This session has been expired (possibly due to multiple concurrent "
|
||||
+ "logins being attempted as the same user).");
|
||||
response.getWriter()
|
||||
.print("This session has been expired (possibly due to multiple concurrent "
|
||||
+ "logins being attempted as the same user).");
|
||||
response.flushBuffer();
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -43,8 +43,11 @@ public final class RequestedUrlRedirectInvalidSessionStrategy implements Invalid
|
||||
|
||||
@Override
|
||||
public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
String destinationUrl = ServletUriComponentsBuilder.fromRequest(request).host(null).scheme(null).port(null)
|
||||
.toUriString();
|
||||
String destinationUrl = ServletUriComponentsBuilder.fromRequest(request)
|
||||
.host(null)
|
||||
.scheme(null)
|
||||
.port(null)
|
||||
.toUriString();
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Starting new session (if required) and redirecting to '" + destinationUrl + "'");
|
||||
}
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ public class SessionManagementFilter extends GenericFilterBean {
|
||||
static final String FILTER_APPLIED = "__spring_security_session_mgmt_filter_applied";
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private final SecurityContextRepository securityContextRepository;
|
||||
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ public class DefaultRedirectStrategyTests {
|
||||
request.setContextPath("/context");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> rds.sendRedirect(request, response, "https://redirectme.somewhere.else"));
|
||||
.isThrownBy(() -> rds.sendRedirect(request, response, "https://redirectme.somewhere.else"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -201,10 +201,10 @@ public class FilterChainProxyTests {
|
||||
given(this.matcher.matches(any(HttpServletRequest.class))).willReturn(true);
|
||||
willAnswer((Answer<Object>) (inv) -> {
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(new TestingAuthenticationToken("username", "password"));
|
||||
.setAuthentication(new TestingAuthenticationToken("username", "password"));
|
||||
return null;
|
||||
}).given(this.filter).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class),
|
||||
any(FilterChain.class));
|
||||
}).given(this.filter)
|
||||
.doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class), any(FilterChain.class));
|
||||
this.fcp.doFilter(this.request, this.response, this.chain);
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
|
||||
}
|
||||
@@ -223,12 +223,12 @@ public class FilterChainProxyTests {
|
||||
given(this.matcher.matches(any(HttpServletRequest.class))).willReturn(true);
|
||||
willAnswer((Answer<Object>) (inv) -> {
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(new TestingAuthenticationToken("username", "password"));
|
||||
.setAuthentication(new TestingAuthenticationToken("username", "password"));
|
||||
throw new ServletException("oops");
|
||||
}).given(this.filter).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class),
|
||||
any(FilterChain.class));
|
||||
}).given(this.filter)
|
||||
.doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class), any(FilterChain.class));
|
||||
assertThatExceptionOfType(ServletException.class)
|
||||
.isThrownBy(() -> this.fcp.doFilter(this.request, this.response, this.chain));
|
||||
.isThrownBy(() -> this.fcp.doFilter(this.request, this.response, this.chain));
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
|
||||
}
|
||||
|
||||
@@ -243,13 +243,13 @@ public class FilterChainProxyTests {
|
||||
willAnswer((Answer<Object>) (inv1) -> {
|
||||
innerChain.doFilter(this.request, this.response);
|
||||
return null;
|
||||
}).given(this.filter).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class),
|
||||
any(FilterChain.class));
|
||||
}).given(this.filter)
|
||||
.doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class), any(FilterChain.class));
|
||||
this.fcp.doFilter(this.request, this.response, innerChain);
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(expected);
|
||||
return null;
|
||||
}).given(this.filter).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class),
|
||||
any(FilterChain.class));
|
||||
}).given(this.filter)
|
||||
.doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class), any(FilterChain.class));
|
||||
this.fcp.doFilter(this.request, this.response, this.chain);
|
||||
verify(innerChain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
|
||||
@@ -297,7 +297,8 @@ public class FilterChainProxyTests {
|
||||
FilterChainProxy fcp = new FilterChainProxy(sec);
|
||||
fcp.setFilterChainDecorator(new ObservationFilterChainDecorator(registry));
|
||||
Filter filter = ObservationFilterChainDecorator.FilterObservation
|
||||
.create(Observation.createNotStarted("wrap", registry)).wrap(fcp);
|
||||
.create(Observation.createNotStarted("wrap", registry))
|
||||
.wrap(fcp);
|
||||
filter.doFilter(this.request, this.response, this.chain);
|
||||
ArgumentCaptor<Observation.Context> captor = ArgumentCaptor.forClass(Observation.Context.class);
|
||||
verify(handler, times(4)).onStart(captor.capture());
|
||||
@@ -323,7 +324,8 @@ public class FilterChainProxyTests {
|
||||
FilterChainProxy fcp = new FilterChainProxy(sec);
|
||||
fcp.setFilterChainDecorator(new ObservationFilterChainDecorator(registry));
|
||||
Filter filter = ObservationFilterChainDecorator.FilterObservation
|
||||
.create(Observation.createNotStarted("wrap", registry)).wrap(fcp);
|
||||
.create(Observation.createNotStarted("wrap", registry))
|
||||
.wrap(fcp);
|
||||
filter.doFilter(this.request, this.response, this.chain);
|
||||
ArgumentCaptor<Observation.Context> captor = ArgumentCaptor.forClass(Observation.Context.class);
|
||||
verify(handler, times(4)).onStart(captor.capture());
|
||||
@@ -345,7 +347,8 @@ public class FilterChainProxyTests {
|
||||
FilterChainProxy fcp = new FilterChainProxy(sec);
|
||||
fcp.setFilterChainDecorator(new ObservationFilterChainDecorator(registry));
|
||||
Filter filter = ObservationFilterChainDecorator.FilterObservation
|
||||
.create(Observation.createNotStarted("wrap", registry)).wrap(fcp);
|
||||
.create(Observation.createNotStarted("wrap", registry))
|
||||
.wrap(fcp);
|
||||
filter.doFilter(this.request, this.response, this.chain);
|
||||
ArgumentCaptor<Observation.Context> captor = ArgumentCaptor.forClass(Observation.Context.class);
|
||||
verify(handler, times(2)).onStart(captor.capture());
|
||||
@@ -367,9 +370,10 @@ public class FilterChainProxyTests {
|
||||
FilterChainProxy fcp = new FilterChainProxy(sec);
|
||||
fcp.setFilterChainDecorator(new ObservationFilterChainDecorator(registry));
|
||||
Filter filter = ObservationFilterChainDecorator.FilterObservation
|
||||
.create(Observation.createNotStarted("wrap", registry)).wrap(fcp);
|
||||
.create(Observation.createNotStarted("wrap", registry))
|
||||
.wrap(fcp);
|
||||
assertThatExceptionOfType(IllegalStateException.class)
|
||||
.isThrownBy(() -> filter.doFilter(this.request, this.response, this.chain));
|
||||
.isThrownBy(() -> filter.doFilter(this.request, this.response, this.chain));
|
||||
ArgumentCaptor<Observation.Context> captor = ArgumentCaptor.forClass(Observation.Context.class);
|
||||
verify(handler, times(2)).onStart(captor.capture());
|
||||
verify(handler, times(2)).onStop(any());
|
||||
@@ -394,9 +398,10 @@ public class FilterChainProxyTests {
|
||||
FilterChainProxy fcp = new FilterChainProxy(sec);
|
||||
fcp.setFilterChainDecorator(new ObservationFilterChainDecorator(registry));
|
||||
Filter filter = ObservationFilterChainDecorator.FilterObservation
|
||||
.create(Observation.createNotStarted("wrap", registry)).wrap(fcp);
|
||||
.create(Observation.createNotStarted("wrap", registry))
|
||||
.wrap(fcp);
|
||||
assertThatExceptionOfType(IllegalStateException.class)
|
||||
.isThrownBy(() -> filter.doFilter(this.request, this.response, this.chain));
|
||||
.isThrownBy(() -> filter.doFilter(this.request, this.response, this.chain));
|
||||
ArgumentCaptor<Observation.Context> captor = ArgumentCaptor.forClass(Observation.Context.class);
|
||||
verify(handler, times(2)).onStart(captor.capture());
|
||||
verify(handler, times(2)).onStop(any());
|
||||
@@ -419,7 +424,8 @@ public class FilterChainProxyTests {
|
||||
FilterChainProxy fcp = new FilterChainProxy(sec);
|
||||
fcp.setFilterChainDecorator(new ObservationFilterChainDecorator(registry));
|
||||
Filter filter = ObservationFilterChainDecorator.FilterObservation
|
||||
.create(Observation.createNotStarted("wrap", registry)).wrap(fcp);
|
||||
.create(Observation.createNotStarted("wrap", registry))
|
||||
.wrap(fcp);
|
||||
filter.doFilter(this.request, this.response, this.chain);
|
||||
ArgumentCaptor<Observation.Context> captor = ArgumentCaptor.forClass(Observation.Context.class);
|
||||
verify(handler, times(3)).onStart(captor.capture());
|
||||
@@ -434,7 +440,7 @@ public class FilterChainProxyTests {
|
||||
assertThat(context).isInstanceOf(ObservationFilterChainDecorator.FilterChainObservationContext.class);
|
||||
ObservationFilterChainDecorator.FilterChainObservationContext filterChainObservationContext = (ObservationFilterChainDecorator.FilterChainObservationContext) context;
|
||||
assertThat(context.getName())
|
||||
.isEqualTo(ObservationFilterChainDecorator.FilterChainObservationConvention.CHAIN_OBSERVATION_NAME);
|
||||
.isEqualTo(ObservationFilterChainDecorator.FilterChainObservationConvention.CHAIN_OBSERVATION_NAME);
|
||||
assertThat(context.getContextualName()).endsWith(filterSection);
|
||||
assertThat(filterChainObservationContext.getChainPosition()).isEqualTo(chainPosition);
|
||||
}
|
||||
|
||||
@@ -77,14 +77,14 @@ public class FilterInvocationTests {
|
||||
public void testRejectsNullServletRequest() {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new FilterInvocation(null, response, mock(FilterChain.class)));
|
||||
.isThrownBy(() -> new FilterInvocation(null, response, mock(FilterChain.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRejectsNullServletResponse() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(null, null);
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new FilterInvocation(request, null, mock(FilterChain.class)));
|
||||
.isThrownBy(() -> new FilterInvocation(request, null, mock(FilterChain.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -123,7 +123,7 @@ public class FilterInvocationTests {
|
||||
@Test
|
||||
public void dummyChainRejectsInvocation() throws Exception {
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> FilterInvocation.DUMMY_CHAIN
|
||||
.doFilter(mock(HttpServletRequest.class), mock(HttpServletResponse.class)));
|
||||
.doFilter(mock(HttpServletRequest.class), mock(HttpServletResponse.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-1
@@ -129,7 +129,7 @@ public class ObservationFilterChainDecoratorTests {
|
||||
ArgumentCaptor<Observation.Context> context = ArgumentCaptor.forClass(Observation.Context.class);
|
||||
verify(handler, times(3)).onScopeClosed(context.capture());
|
||||
assertThat(context.getValue().getLowCardinalityKeyValue("spring.security.reached.filter.name").getValue())
|
||||
.isEqualTo(expectedFilterNameTag);
|
||||
.isEqualTo(expectedFilterNameTag);
|
||||
}
|
||||
|
||||
static Stream<Arguments> decorateFiltersWhenCompletesThenHasSpringSecurityReachedFilterNameTag() {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user