Describe the bug
Spring Security version 6.5.0 release.
Since the AntPathMatcher
is deprecated, I replaced it with PathPatternRequestMatcher
expecting that it would behave the same. However I discovered that the PathPatternRequestMatcher
caches the parsed RequestPath
in a request attribute (see org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher#getPathContainer
). This leads to unexpected behavior when forwarding.
For example if you make a request to /path-a
then call request.getRequestDispatcher("/path-b").forward(request, response)
then a PathPatternRequestMatcher
will never match on /path-b
(assuming that /path-a
was cached in the request, in my case by a filter earlier in the chain which uses a PathPatternRequestMatcher
).
To Reproduce
- Make request to
/path-a
- Use any PathPatternRequestMatcher on the request e.g.
PathPatternRequestMatcher.withDefaults().matcher("/path-a").matches(request)
- Forward the request
request.getRequestDispatcher("/path-b").forward(request, response)
- After forwarding
PathPatternRequestMatcher.withDefaults().matcher("/path-b").matches(request)
will return false
Expected behavior
The PathPatternRequestMatcher
should behave the same as the AntPathMatcher
which it is replacing and always match on the jakarta.servlet.http.HttpServletRequest#getRequestURI
.
Sample
Can supply if required.
Screenshot
Screenshot illustrating the issue
Comment From: jazdw
@jzheaux I also noticed that org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher#servletPath
is never written, org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher#method
could be final and initialized via the constructor also.
Comment From: jazdw
Another tidbit I just discovered is that org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration#springSecurityPathPatternParserBeanDefinitionRegistryPostProcessor
now adds a org.springframework.web.filter.ServletRequestPathFilter
before the spring security filter chain. This is not mentioned in the 6.5.0 release notes.
Comment From: jazdw
You can prevent the automatic registration of the ServletRequestPathFilter
filter by overriding the bean:
@Bean
static BeanDefinitionRegistryPostProcessor springSecurityPathPatternParserBeanDefinitionRegistryPostProcessor() {
// noop post processor
return registry -> {};
}
I think the reason we are encountering this issue in our application is that we register the DelegatingFilterProxy
using our own initializer and it does not handle jakarta.servlet.DispatcherType#FORWARD
. Our workaround is to disable the BeanDefinitionRegistryPostProcessor
as above, then register our own ServletRequestPathFilter
which does handle the FORWARD
dispatch.
Comment From: jzheaux
Thanks for the detail, @jazdw. Are you able to provide a sample app that reproduces the issue?