Move Web Access API

Issue gh-17847
This commit is contained in:
Josh Cummings 2025-09-02 16:06:03 -06:00
parent 3182883e2e
commit fa4806dbcc
No known key found for this signature in database
GPG Key ID: 869B37A20E876129
35 changed files with 67 additions and 54 deletions

View File

@ -12,6 +12,7 @@ dependencies {
api 'io.micrometer:micrometer-observation' api 'io.micrometer:micrometer-observation'
optional project(':spring-security-messaging') optional project(':spring-security-messaging')
optional project(':spring-security-web')
optional 'org.springframework:spring-websocket' optional 'org.springframework:spring-websocket'
optional 'com.fasterxml.jackson.core:jackson-databind' optional 'com.fasterxml.jackson.core:jackson-databind'
optional 'io.micrometer:context-propagation' optional 'io.micrometer:context-propagation'
@ -22,6 +23,9 @@ dependencies {
optional 'org.springframework:spring-tx' optional 'org.springframework:spring-tx'
optional 'org.jetbrains.kotlinx:kotlinx-coroutines-reactor' optional 'org.jetbrains.kotlinx:kotlinx-coroutines-reactor'
provided 'jakarta.servlet:jakarta.servlet-api'
testImplementation project(path : ':spring-security-web', configuration : 'tests')
testImplementation 'commons-collections:commons-collections' testImplementation 'commons-collections:commons-collections'
testImplementation 'io.projectreactor:reactor-test' testImplementation 'io.projectreactor:reactor-test'
testImplementation "org.assertj:assertj-core" testImplementation "org.assertj:assertj-core"

View File

@ -16,9 +16,13 @@
package org.springframework.security.web.access; package org.springframework.security.web.access;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.mock.web.MockServletContext; import org.springframework.mock.web.MockServletContext;
@ -33,15 +37,6 @@ import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/** /**
* Tests * Tests
* {@link org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator}. * {@link org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator}.
@ -61,43 +56,45 @@ public class DefaultWebInvocationPrivilegeEvaluatorTests {
@BeforeEach @BeforeEach
public final void setUp() { public final void setUp() {
this.interceptor = new FilterSecurityInterceptor(); this.interceptor = new FilterSecurityInterceptor();
this.ods = mock(FilterInvocationSecurityMetadataSource.class); this.ods = Mockito.mock(FilterInvocationSecurityMetadataSource.class);
this.adm = mock(AccessDecisionManager.class); this.adm = Mockito.mock(AccessDecisionManager.class);
this.ram = mock(RunAsManager.class); this.ram = Mockito.mock(RunAsManager.class);
this.interceptor.setAuthenticationManager(mock(AuthenticationManager.class)); this.interceptor.setAuthenticationManager(Mockito.mock(AuthenticationManager.class));
this.interceptor.setSecurityMetadataSource(this.ods); this.interceptor.setSecurityMetadataSource(this.ods);
this.interceptor.setAccessDecisionManager(this.adm); this.interceptor.setAccessDecisionManager(this.adm);
this.interceptor.setRunAsManager(this.ram); this.interceptor.setRunAsManager(this.ram);
this.interceptor.setApplicationEventPublisher(mock(ApplicationEventPublisher.class)); this.interceptor.setApplicationEventPublisher(Mockito.mock(ApplicationEventPublisher.class));
SecurityContextHolder.clearContext(); SecurityContextHolder.clearContext();
} }
@Test @Test
public void permitsAccessIfNoMatchingAttributesAndPublicInvocationsAllowed() { public void permitsAccessIfNoMatchingAttributesAndPublicInvocationsAllowed() {
DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor); DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor);
given(this.ods.getAttributes(any())).willReturn(null); BDDMockito.given(this.ods.getAttributes(ArgumentMatchers.any())).willReturn(null);
assertThat(wipe.isAllowed("/context", "/foo/index.jsp", "GET", mock(Authentication.class))).isTrue(); Assertions.assertThat(wipe.isAllowed("/context", "/foo/index.jsp", "GET", Mockito.mock(Authentication.class)))
.isTrue();
} }
@Test @Test
public void deniesAccessIfNoMatchingAttributesAndPublicInvocationsNotAllowed() { public void deniesAccessIfNoMatchingAttributesAndPublicInvocationsNotAllowed() {
DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor); DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor);
given(this.ods.getAttributes(any())).willReturn(null); BDDMockito.given(this.ods.getAttributes(ArgumentMatchers.any())).willReturn(null);
this.interceptor.setRejectPublicInvocations(true); this.interceptor.setRejectPublicInvocations(true);
assertThat(wipe.isAllowed("/context", "/foo/index.jsp", "GET", mock(Authentication.class))).isFalse(); Assertions.assertThat(wipe.isAllowed("/context", "/foo/index.jsp", "GET", Mockito.mock(Authentication.class)))
.isFalse();
} }
@Test @Test
public void deniesAccessIfAuthenticationIsNull() { public void deniesAccessIfAuthenticationIsNull() {
DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor); DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor);
assertThat(wipe.isAllowed("/foo/index.jsp", null)).isFalse(); Assertions.assertThat(wipe.isAllowed("/foo/index.jsp", null)).isFalse();
} }
@Test @Test
public void allowsAccessIfAccessDecisionManagerDoes() { public void allowsAccessIfAccessDecisionManagerDoes() {
Authentication token = new TestingAuthenticationToken("test", "Password", "MOCK_INDEX"); Authentication token = new TestingAuthenticationToken("test", "Password", "MOCK_INDEX");
DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor); DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor);
assertThat(wipe.isAllowed("/foo/index.jsp", token)).isTrue(); Assertions.assertThat(wipe.isAllowed("/foo/index.jsp", token)).isTrue();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -105,8 +102,10 @@ public class DefaultWebInvocationPrivilegeEvaluatorTests {
public void deniesAccessIfAccessDecisionManagerDoes() { public void deniesAccessIfAccessDecisionManagerDoes() {
Authentication token = new TestingAuthenticationToken("test", "Password", "MOCK_INDEX"); Authentication token = new TestingAuthenticationToken("test", "Password", "MOCK_INDEX");
DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor); DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor);
willThrow(new AccessDeniedException("")).given(this.adm).decide(any(Authentication.class), any(), anyList()); BDDMockito.willThrow(new AccessDeniedException(""))
assertThat(wipe.isAllowed("/foo/index.jsp", token)).isFalse(); .given(this.adm)
.decide(ArgumentMatchers.any(Authentication.class), ArgumentMatchers.any(), ArgumentMatchers.anyList());
Assertions.assertThat(wipe.isAllowed("/foo/index.jsp", token)).isFalse();
} }
@Test @Test
@ -118,8 +117,9 @@ public class DefaultWebInvocationPrivilegeEvaluatorTests {
DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor); DefaultWebInvocationPrivilegeEvaluator wipe = new DefaultWebInvocationPrivilegeEvaluator(this.interceptor);
wipe.setServletContext(servletContext); wipe.setServletContext(servletContext);
wipe.isAllowed("/foo/index.jsp", token); wipe.isAllowed("/foo/index.jsp", token);
verify(this.adm).decide(eq(token), filterInvocationArgumentCaptor.capture(), any()); Mockito.verify(this.adm)
assertThat(filterInvocationArgumentCaptor.getValue().getRequest().getServletContext()).isNotNull(); .decide(ArgumentMatchers.eq(token), filterInvocationArgumentCaptor.capture(), ArgumentMatchers.any());
Assertions.assertThat(filterInvocationArgumentCaptor.getValue().getRequest().getServletContext()).isNotNull();
} }
} }

View File

@ -23,6 +23,7 @@ import java.util.List;
import java.util.Vector; import java.util.Vector;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
@ -85,7 +86,7 @@ public class ChannelDecisionManagerImplTests {
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
List<ConfigAttribute> cad = SecurityConfig.createList("xyz"); List<ConfigAttribute> cad = SecurityConfig.createList("xyz");
cdm.decide(fi, cad); cdm.decide(fi, cad);
assertThat(fi.getResponse().isCommitted()).isTrue(); Assertions.assertThat(fi.getResponse().isCommitted()).isTrue();
} }
@Test @Test
@ -100,7 +101,7 @@ public class ChannelDecisionManagerImplTests {
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
cdm.decide(fi, SecurityConfig.createList(new String[] { "abc", "ANY_CHANNEL" })); cdm.decide(fi, SecurityConfig.createList(new String[] { "abc", "ANY_CHANNEL" }));
assertThat(fi.getResponse().isCommitted()).isFalse(); Assertions.assertThat(fi.getResponse().isCommitted()).isFalse();
} }
@Test @Test
@ -117,7 +118,7 @@ public class ChannelDecisionManagerImplTests {
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
cdm.decide(fi, SecurityConfig.createList("SOME_ATTRIBUTE_NO_PROCESSORS_SUPPORT")); cdm.decide(fi, SecurityConfig.createList("SOME_ATTRIBUTE_NO_PROCESSORS_SUPPORT"));
assertThat(fi.getResponse().isCommitted()).isFalse(); Assertions.assertThat(fi.getResponse().isCommitted()).isFalse();
} }
@Test @Test

View File

@ -28,11 +28,11 @@ import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig; import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.servlet.TestMockHttpServletRequests;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get;
/** /**
* Tests {@link ChannelProcessingFilter}. * Tests {@link ChannelProcessingFilter}.
@ -82,7 +82,7 @@ public class ChannelProcessingFilterTests {
filter.setChannelDecisionManager(new MockChannelDecisionManager(true, "SOME_ATTRIBUTE")); filter.setChannelDecisionManager(new MockChannelDecisionManager(true, "SOME_ATTRIBUTE"));
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SOME_ATTRIBUTE"); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SOME_ATTRIBUTE");
filter.setSecurityMetadataSource(fids); filter.setSecurityMetadataSource(fids);
MockHttpServletRequest request = get("/path").build(); MockHttpServletRequest request = TestMockHttpServletRequests.get("/path").build();
request.setQueryString("info=now"); request.setQueryString("info=now");
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
filter.doFilter(request, response, mock(FilterChain.class)); filter.doFilter(request, response, mock(FilterChain.class));
@ -94,7 +94,7 @@ public class ChannelProcessingFilterTests {
filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "SOME_ATTRIBUTE")); filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "SOME_ATTRIBUTE"));
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SOME_ATTRIBUTE"); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SOME_ATTRIBUTE");
filter.setSecurityMetadataSource(fids); filter.setSecurityMetadataSource(fids);
MockHttpServletRequest request = get("/path").build(); MockHttpServletRequest request = TestMockHttpServletRequests.get("/path").build();
request.setQueryString("info=now"); request.setQueryString("info=now");
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
filter.doFilter(request, response, mock(FilterChain.class)); filter.doFilter(request, response, mock(FilterChain.class));
@ -106,7 +106,7 @@ public class ChannelProcessingFilterTests {
filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "NOT_USED")); filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "NOT_USED"));
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "NOT_USED"); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "NOT_USED");
filter.setSecurityMetadataSource(fids); filter.setSecurityMetadataSource(fids);
MockHttpServletRequest request = get("/PATH_NOT_MATCHING_CONFIG_ATTRIBUTE").build(); MockHttpServletRequest request = TestMockHttpServletRequests.get("/PATH_NOT_MATCHING_CONFIG_ATTRIBUTE").build();
request.setQueryString("info=now"); request.setQueryString("info=now");
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
filter.doFilter(request, response, mock(FilterChain.class)); filter.doFilter(request, response, mock(FilterChain.class));

View File

@ -17,17 +17,18 @@
package org.springframework.security.web.access.channel; package org.springframework.security.web.access.channel;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.access.SecurityConfig; import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.servlet.TestMockHttpServletRequests;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get;
/** /**
* Tests {@link InsecureChannelProcessor}. * Tests {@link InsecureChannelProcessor}.
@ -38,19 +39,21 @@ public class InsecureChannelProcessorTests {
@Test @Test
public void testDecideDetectsAcceptableChannel() throws Exception { public void testDecideDetectsAcceptableChannel() throws Exception {
MockHttpServletRequest request = get("http://localhost:8080").requestUri("/bigapp", "/servlet", null) MockHttpServletRequest request = TestMockHttpServletRequests.get("http://localhost:8080")
.requestUri("/bigapp", "/servlet", null)
.queryString("info=true") .queryString("info=true")
.build(); .build();
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
InsecureChannelProcessor processor = new InsecureChannelProcessor(); InsecureChannelProcessor processor = new InsecureChannelProcessor();
processor.decide(fi, SecurityConfig.createList("SOME_IGNORED_ATTRIBUTE", "REQUIRES_INSECURE_CHANNEL")); processor.decide(fi, SecurityConfig.createList("SOME_IGNORED_ATTRIBUTE", "REQUIRES_INSECURE_CHANNEL"));
assertThat(fi.getResponse().isCommitted()).isFalse(); Assertions.assertThat(fi.getResponse().isCommitted()).isFalse();
} }
@Test @Test
public void testDecideDetectsUnacceptableChannel() throws Exception { public void testDecideDetectsUnacceptableChannel() throws Exception {
MockHttpServletRequest request = get("https://localhost:8443").requestUri("/bigapp", "/servlet", null) MockHttpServletRequest request = TestMockHttpServletRequests.get("https://localhost:8443")
.requestUri("/bigapp", "/servlet", null)
.queryString("info=true") .queryString("info=true")
.build(); .build();
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
@ -58,7 +61,7 @@ public class InsecureChannelProcessorTests {
InsecureChannelProcessor processor = new InsecureChannelProcessor(); InsecureChannelProcessor processor = new InsecureChannelProcessor();
processor.decide(fi, processor.decide(fi,
SecurityConfig.createList(new String[] { "SOME_IGNORED_ATTRIBUTE", "REQUIRES_INSECURE_CHANNEL" })); SecurityConfig.createList(new String[] { "SOME_IGNORED_ATTRIBUTE", "REQUIRES_INSECURE_CHANNEL" }));
assertThat(fi.getResponse().isCommitted()).isTrue(); Assertions.assertThat(fi.getResponse().isCommitted()).isTrue();
} }
@Test @Test

View File

@ -17,17 +17,18 @@
package org.springframework.security.web.access.channel; package org.springframework.security.web.access.channel;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.access.SecurityConfig; import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.servlet.TestMockHttpServletRequests;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get;
/** /**
* Tests {@link SecureChannelProcessor}. * Tests {@link SecureChannelProcessor}.
@ -38,19 +39,21 @@ public class SecureChannelProcessorTests {
@Test @Test
public void testDecideDetectsAcceptableChannel() throws Exception { public void testDecideDetectsAcceptableChannel() throws Exception {
MockHttpServletRequest request = get("https://localhost:8443").requestUri("/bigapp", "/servlet", null) MockHttpServletRequest request = TestMockHttpServletRequests.get("https://localhost:8443")
.requestUri("/bigapp", "/servlet", null)
.queryString("info=true") .queryString("info=true")
.build(); .build();
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class));
SecureChannelProcessor processor = new SecureChannelProcessor(); SecureChannelProcessor processor = new SecureChannelProcessor();
processor.decide(fi, SecurityConfig.createList("SOME_IGNORED_ATTRIBUTE", "REQUIRES_SECURE_CHANNEL")); processor.decide(fi, SecurityConfig.createList("SOME_IGNORED_ATTRIBUTE", "REQUIRES_SECURE_CHANNEL"));
assertThat(fi.getResponse().isCommitted()).isFalse(); Assertions.assertThat(fi.getResponse().isCommitted()).isFalse();
} }
@Test @Test
public void testDecideDetectsUnacceptableChannel() throws Exception { public void testDecideDetectsUnacceptableChannel() throws Exception {
MockHttpServletRequest request = get("http://localhost:8080").requestUri("/bigapp", "/servlet", null) MockHttpServletRequest request = TestMockHttpServletRequests.get("http://localhost:8080")
.requestUri("/bigapp", "/servlet", null)
.queryString("info=true") .queryString("info=true")
.build(); .build();
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
@ -58,7 +61,7 @@ public class SecureChannelProcessorTests {
SecureChannelProcessor processor = new SecureChannelProcessor(); SecureChannelProcessor processor = new SecureChannelProcessor();
processor.decide(fi, processor.decide(fi,
SecurityConfig.createList(new String[] { "SOME_IGNORED_ATTRIBUTE", "REQUIRES_SECURE_CHANNEL" })); SecurityConfig.createList(new String[] { "SOME_IGNORED_ATTRIBUTE", "REQUIRES_SECURE_CHANNEL" }));
assertThat(fi.getResponse().isCommitted()).isTrue(); Assertions.assertThat(fi.getResponse().isCommitted()).isTrue();
} }
@Test @Test

View File

@ -28,12 +28,12 @@ import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig; import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.servlet.TestMockHttpServletRequests;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.springframework.security.web.servlet.TestMockHttpServletRequests.request;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
/** /**
* Tests {@link DefaultFilterInvocationSecurityMetadataSource}. * Tests {@link DefaultFilterInvocationSecurityMetadataSource}.
@ -48,7 +48,7 @@ public class DefaultFilterInvocationSecurityMetadataSourceTests {
private void createFids(String pattern, HttpMethod method) { private void createFids(String pattern, HttpMethod method) {
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<>(); LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<>();
requestMap.put(pathPattern(method, pattern), this.def); requestMap.put(PathPatternRequestMatcher.pathPattern(method, pattern), this.def);
this.fids = new DefaultFilterInvocationSecurityMetadataSource(requestMap); this.fids = new DefaultFilterInvocationSecurityMetadataSource(requestMap);
} }
@ -117,8 +117,9 @@ public class DefaultFilterInvocationSecurityMetadataSourceTests {
public void mixingPatternsWithAndWithoutHttpMethodsIsSupported() { public void mixingPatternsWithAndWithoutHttpMethodsIsSupported() {
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<>(); LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<>();
Collection<ConfigAttribute> userAttrs = SecurityConfig.createList("A"); Collection<ConfigAttribute> userAttrs = SecurityConfig.createList("A");
requestMap.put(pathPattern("/user/**"), userAttrs); requestMap.put(PathPatternRequestMatcher.pathPattern("/user/**"), userAttrs);
requestMap.put(pathPattern(HttpMethod.GET, "/teller/**"), SecurityConfig.createList("B")); requestMap.put(PathPatternRequestMatcher.pathPattern(HttpMethod.GET, "/teller/**"),
SecurityConfig.createList("B"));
this.fids = new DefaultFilterInvocationSecurityMetadataSource(requestMap); this.fids = new DefaultFilterInvocationSecurityMetadataSource(requestMap);
FilterInvocation fi = createFilterInvocation("/user", null, null, "GET"); FilterInvocation fi = createFilterInvocation("/user", null, null, "GET");
Collection<ConfigAttribute> attrs = this.fids.getAttributes(fi); Collection<ConfigAttribute> attrs = this.fids.getAttributes(fi);
@ -141,7 +142,8 @@ public class DefaultFilterInvocationSecurityMetadataSourceTests {
private FilterInvocation createFilterInvocation(String servletPath, String pathInfo, String queryString, private FilterInvocation createFilterInvocation(String servletPath, String pathInfo, String queryString,
String method) { String method) {
MockHttpServletRequest request = request(method).requestUri(null, servletPath, pathInfo) MockHttpServletRequest request = TestMockHttpServletRequests.request(method)
.requestUri(null, servletPath, pathInfo)
.queryString(queryString) .queryString(queryString)
.build(); .build();
return new FilterInvocation(request, new MockHttpServletResponse(), mock(FilterChain.class)); return new FilterInvocation(request, new MockHttpServletResponse(), mock(FilterChain.class));

View File

@ -39,6 +39,7 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.servlet.TestMockHttpServletRequests;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -53,7 +54,6 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get;
/** /**
* Tests {@link FilterSecurityInterceptor}. * Tests {@link FilterSecurityInterceptor}.
@ -189,7 +189,7 @@ public class FilterSecurityInterceptorTests {
private FilterInvocation createinvocation() { private FilterInvocation createinvocation() {
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
MockHttpServletRequest request = get("/secure/page.html").build(); MockHttpServletRequest request = TestMockHttpServletRequests.get("/secure/page.html").build();
FilterChain chain = mock(FilterChain.class); FilterChain chain = mock(FilterChain.class);
FilterInvocation fi = new FilterInvocation(request, response, chain); FilterInvocation fi = new FilterInvocation(request, response, chain);
return fi; return fi;

View File

@ -21,6 +21,7 @@ dependencies {
testRuntimeOnly 'jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api' testRuntimeOnly 'jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api'
testImplementation project(':spring-security-access')
testImplementation "org.assertj:assertj-core" testImplementation "org.assertj:assertj-core"
testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.junit.jupiter:junit-jupiter-api"
testImplementation "org.junit.jupiter:junit-jupiter-params" testImplementation "org.junit.jupiter:junit-jupiter-params"

View File

@ -39,7 +39,6 @@ dependencies {
api 'org.springframework:spring-expression' api 'org.springframework:spring-expression'
api 'org.springframework:spring-web' api 'org.springframework:spring-web'
optional project(':spring-security-access')
optional 'com.fasterxml.jackson.core:jackson-databind' optional 'com.fasterxml.jackson.core:jackson-databind'
optional 'io.micrometer:context-propagation' optional 'io.micrometer:context-propagation'
optional 'io.projectreactor:reactor-core' optional 'io.projectreactor:reactor-core'

View File

@ -32,10 +32,10 @@ import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression; import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser; import org.springframework.expression.ExpressionParser;
import org.springframework.expression.TypedValue; import org.springframework.expression.TypedValue;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.access.expression.SecurityExpressionRoot; import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.authentication.AuthenticationTrustResolver; import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext; import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
@ -73,15 +73,15 @@ public class DefaultHttpSecurityExpressionHandlerTests {
@Test @Test
public void expressionPropertiesAreResolvedAgainstAppContextBeans() { public void expressionPropertiesAreResolvedAgainstAppContextBeans() {
StaticApplicationContext appContext = new StaticApplicationContext(); StaticApplicationContext appContext = new StaticApplicationContext();
RootBeanDefinition bean = new RootBeanDefinition(SecurityConfig.class); RootBeanDefinition bean = new RootBeanDefinition(SimpleGrantedAuthority.class);
bean.getConstructorArgumentValues().addGenericArgumentValue("ROLE_A"); bean.getConstructorArgumentValues().addGenericArgumentValue("ROLE_A");
appContext.registerBeanDefinition("role", bean); appContext.registerBeanDefinition("role", bean);
this.handler.setApplicationContext(appContext); this.handler.setApplicationContext(appContext);
EvaluationContext ctx = this.handler.createEvaluationContext(mock(Authentication.class), EvaluationContext ctx = this.handler.createEvaluationContext(mock(Authentication.class),
mock(RequestAuthorizationContext.class)); mock(RequestAuthorizationContext.class));
ExpressionParser parser = this.handler.getExpressionParser(); ExpressionParser parser = this.handler.getExpressionParser();
assertThat(parser.parseExpression("@role.getAttribute() == 'ROLE_A'").getValue(ctx, Boolean.class)).isTrue(); assertThat(parser.parseExpression("@role.getAuthority() == 'ROLE_A'").getValue(ctx, Boolean.class)).isTrue();
assertThat(parser.parseExpression("@role.attribute == 'ROLE_A'").getValue(ctx, Boolean.class)).isTrue(); assertThat(parser.parseExpression("@role.authority == 'ROLE_A'").getValue(ctx, Boolean.class)).isTrue();
} }
@Test @Test