Skip to content

WebInvocationPrivilegeEvaluator throws UnsupportedOperationException when a dispatcherTypeMatcher is configured. #19131

@maartenc

Description

@maartenc

Describe the bug

We are using a WebInvocationPrivilegeEvaluator to evaluate if a user has access to some paths.
After upgrading Spring Security from 6.5.10 to 7.0.4, this now throws a java.lang.UnsupportedOperationException.

To Reproduce

Configure some dispatcherTypeMatcher in your HttpSecurity.
For instance:

httpSecurity.authorizeHttpRequests(authorizedRequests -> 
    authorizedRequests.dispatcherTypeMatchers(DispatcherType.ERROR, DispatcherType.FORWARD)
                      .permitAll());

Create a controller, and let Spring inject a WebInvocationPrivilegeEvaluator bean:

@RestController
@RequestMapping("/check-access")
public class MyController {

  private final WebInvocationPrivilegeEvaluator privilegeEvaluator;

  @Autowired
  public MyController(WebInvocationPrivilegeEvaluator aPrivilegeEvaluator) {
    privilegeEvaluator = aPrivilegeEvaluator;
  }

  @GetMapping("/anonymous")
  public boolean checkAnonymousAccess() {
      return privilegeEvaluator.isAllowed("/foo", new AnonymousAuthenticationToken("anonymous", "anonymous", List.of()));
  }
}

Expected behavior

A working check that validates if the path is allowed according to the configured access rules in the HttpSecurity bean.

Actual behavior

java.lang.UnsupportedOperationException: public abstract jakarta.servlet.DispatcherType jakarta.servlet.ServletRequest.getDispatcherType() is not supported
	at org.springframework.security.web.FilterInvocation$UnsupportedOperationExceptionInvocationHandler.invoke(FilterInvocation.java:332)
	at jdk.proxy3/jdk.proxy3.$Proxy241.getDispatcherType(Unknown Source)
	at jakarta.servlet.ServletRequestWrapper.getDispatcherType(ServletRequestWrapper.java:438)
	at jakarta.servlet.ServletRequestWrapper.getDispatcherType(ServletRequestWrapper.java:438)
	at org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher.matches(DispatcherTypeRequestMatcher.java:72)
	at org.springframework.security.web.util.matcher.RequestMatcher.matcher(RequestMatcher.java:49)
	at org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.authorize(RequestMatcherDelegatingAuthorizationManager.java:75)
	at org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.authorize(RequestMatcherDelegatingAuthorizationManager.java:52)
	at org.springframework.security.authorization.ObservationAuthorizationManager.authorize(ObservationAuthorizationManager.java:75)
	at org.springframework.security.config.annotation.web.builders.WebSecurity.lambda$addAuthorizationManager$2(WebSecurity.java:384)
	at org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.authorize(RequestMatcherDelegatingAuthorizationManager.java:82)
	at org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.authorize(RequestMatcherDelegatingAuthorizationManager.java:52)
	at org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.isAllowed(AuthorizationManagerWebInvocationPrivilegeEvaluator.java:62)
	at org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.isAllowed(AuthorizationManagerWebInvocationPrivilegeEvaluator.java:54)
	at org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator.isAllowed(RequestMatcherDelegatingWebInvocationPrivilegeEvaluator.java:82)
	at com.test.MyController.checkAnonymousAccess(Unknown Source)

Evaluation

The reason this worked with Spring Security 6.5.10 is that in that version, the HandlerMappingIntrospectorRequestTransformer is used to transform the request. That transformer returns a CacheableRequestWrapper that always returns REQUEST as DispatcherType. In Spring Security 7.0.4, this class no longer exist and the DispatcherType is retrieved from the FilterInvocation.DummyRequest class, which throws an UnsupportedOperationException.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions