Merge branch '2.7.x'

This commit is contained in:
Andy Wilkinson
2022-01-20 12:37:16 +00:00
11 changed files with 363 additions and 89 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2021 the original author or authors.
* Copyright 2012-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
import org.springframework.web.util.UrlPathHelper;
/**
* {@link Filter} that intercepts error dispatches to ensure authorized access to the
@@ -47,12 +48,15 @@ public class ErrorPageSecurityFilter implements Filter {
private static final WebInvocationPrivilegeEvaluator ALWAYS = new AlwaysAllowWebInvocationPrivilegeEvaluator();
private final UrlPathHelper urlPathHelper = new UrlPathHelper();
private final ApplicationContext context;
private volatile WebInvocationPrivilegeEvaluator privilegeEvaluator;
public ErrorPageSecurityFilter(ApplicationContext context) {
this.context = context;
this.urlPathHelper.setAlwaysUseFullPath(true);
}
@Override
@@ -76,7 +80,7 @@ public class ErrorPageSecurityFilter implements Filter {
if (isUnauthenticated(authentication) && isNotAuthenticationError(errorCode)) {
return true;
}
return getPrivilegeEvaluator().isAllowed(request.getRequestURI(), authentication);
return getPrivilegeEvaluator().isAllowed(this.urlPathHelper.getPathWithinApplication(request), authentication);
}
private boolean isUnauthenticated(Authentication authentication) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2021 the original author or authors.
* Copyright 2012-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willThrow;
import static org.mockito.Mockito.mock;
@@ -118,4 +119,30 @@ class ErrorPageSecurityFilterTests {
verify(this.filterChain).doFilter(this.request, this.response);
}
@Test
void whenThereIsAContextPathAndServletIsMappedToSlashContextPathIsNotPassedToEvaluator() throws Exception {
SecurityContext securityContext = mock(SecurityContext.class);
SecurityContextHolder.setContext(securityContext);
given(securityContext.getAuthentication()).willReturn(mock(Authentication.class));
this.request.setRequestURI("/example/error");
this.request.setContextPath("/example");
// Servlet mapped to /
this.request.setServletPath("/error");
this.securityFilter.doFilter(this.request, this.response, this.filterChain);
verify(this.privilegeEvaluator).isAllowed(eq("/error"), any());
}
@Test
void whenThereIsAContextPathAndServletIsMappedToWildcardPathCorrectPathIsPassedToEvaluator() throws Exception {
SecurityContext securityContext = mock(SecurityContext.class);
SecurityContextHolder.setContext(securityContext);
given(securityContext.getAuthentication()).willReturn(mock(Authentication.class));
this.request.setRequestURI("/example/dispatcher/path/error");
this.request.setContextPath("/example");
// Servlet mapped to /dispatcher/path/*
this.request.setServletPath("/dispatcher/path");
this.securityFilter.doFilter(this.request, this.response, this.filterChain);
verify(this.privilegeEvaluator).isAllowed(eq("/dispatcher/path/error"), any());
}
}