Description
Describe the bug
The core HttpSecurity
builder supports dispatcherTypeMatchers
, but FilterInvocation
throws UnsupportedOperationException
if they are invoked.
During an upgrade of an older Boot Servlet project, I ran into the problem where the Spring Boot /error
mapping is no longer allowed by default, at least for 403 errors. I tried the suggested resolution of adding dispatcherTypeMatchers(ERROR).permitAll()
to my SecurityFilterChain
bean. This throws an exception in 5.7.11 (the default with the last Boot 2.7) and 5.8.12.
The problem appears to be that DefaultWebInvocationPrivilegeEvaluator
uses a DummyRequest
instead of the real request but does not implement core API methods; many/most other methods were supported as part of #8566.
To Reproduce
- Register
dispatcherTypeMatchers(ERROR).permitAll()
in aSecurityFilterChain
. - Make a request that triggers a 403 response as an unauthenticated user. (
AnonymousAuthenticationToken
)
Expected behavior
The matcher permits the error page to proceed.
Actual behavior
2024-05-10T18:43:15,654Z [http-nio-5000-exec-1] ERROR o.a.c.c.C.[Tomcat].[localhost] - Exception Processing ErrorPage[errorCode=0, location=/error]
java.lang.UnsupportedOperationException: public abstract javax.servlet.DispatcherType javax.servlet.ServletRequest.getDispatcherType() is not supported
at org.springframework.security.web.FilterInvocation$UnsupportedOperationExceptionInvocationHandler.invoke(FilterInvocation.java:331)
at com.sun.proxy.$Proxy84.getDispatcherType(Unknown Source)
at javax.servlet.ServletRequestWrapper.getDispatcherType(ServletRequestWrapper.java:449)
at org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher.matches(DispatcherTypeRequestMatcher.java:72)
at org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource.getAttributes(DefaultFilterInvocationSecurityMetadataSource.java:84)
at org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator.isAllowed(DefaultWebInvocationPrivilegeEvaluator.java:94)
at org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator.isAllowed(DefaultWebInvocationPrivilegeEvaluator.java:69)
at org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator.isAllowed(RequestMatcherDelegatingWebInvocationPrivilegeEvaluator.java:76)
at org.springframework.boot.web.servlet.filter.ErrorPageSecurityFilter.isAllowed(ErrorPageSecurityFilter.java:88)
at org.springframework.boot.web.servlet.filter.ErrorPageSecurityFilter.doFilter(ErrorPageSecurityFilter.java:76)
at org.springframework.boot.web.servlet.filter.ErrorPageSecurityFilter.doFilter(ErrorPageSecurityFilter.java:70)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:352)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:108)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:361)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:361)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:91)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:361)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)