Skip to content

Spring Security Authorization Filter

Spring Security supports to easily configure role or authority for a specified resource by using Spring security expression.

For example,

Java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    ...
    .antMatchers("/auth/admin/*").hasRole("ADMIN")
    .antMatchers("/auth/*").hasAnyRole("ADMIN","USER")
    ...
}

But I am still intertersted how the authorization is checked for a specified resource of a user, that what the AuthorizationFilter, RequestMatcherDelegatingAuthorizationManager and AuthorityAuthorizationManager do the work.

  • In AuthorizationFilter, it calls RequestMatcherDelegatingAuthorizationManager.check to check the authority of the request

    Java
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
                throws ServletException, IOException {
    
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
    
            if (this.observeOncePerRequest && isApplied(request)) {
                chain.doFilter(request, response);
                return;
            }
    
            if (skipDispatch(request)) {
                chain.doFilter(request, response);
                return;
            }
    
            String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
            request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
            try {
                AuthorizationDecision decision = this.authorizationManager.check(this::getAuthentication, request);
                this.eventPublisher.publishAuthorizationEvent(this::getAuthentication, request, decision);
                if (decision != null && !decision.isGranted()) {
                    throw new AccessDeniedException("Access Denied");
                }
                chain.doFilter(request, response);
            }
            finally {
                request.removeAttribute(alreadyFilteredAttributeName);
            }
        }
    
  • In RequestMatcherDelegatingAuthorizationManager.check method, it find the AuthorizationManager<RequestAuthorizationContext> by the request url

    Java
    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, HttpServletRequest request) {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace(LogMessage.format("Authorizing %s", request));
        }
        for (RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>> mapping : this.mappings) {
    
            RequestMatcher matcher = mapping.getRequestMatcher();
            MatchResult matchResult = matcher.matcher(request);
            if (matchResult.isMatch()) {
                AuthorizationManager<RequestAuthorizationContext> manager = mapping.getEntry();
                if (this.logger.isTraceEnabled()) {
                    this.logger.trace(LogMessage.format("Checking authorization on %s using %s", request, manager));
                }
                return manager.check(authentication,
                        new RequestAuthorizationContext(request, matchResult.getVariables()));
            }
        }
        if (this.logger.isTraceEnabled()) {
            this.logger.trace(LogMessage.of(() -> "Denying request since did not find matching RequestMatcher"));
        }
        return DENY;
    }
    
  • In AuthorizationManager.check method, it check if user has the required authority.

    Java
    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, T object) {
        boolean granted = isGranted(authentication.get());
        return new AuthorityAuthorizationDecision(granted, this.authorities);
    }