or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

authentication-filters.mdauthorization.mdcsrf-protection.mdfilter-chain.mdfirewall.mdindex.mdlogout.mdreactive-security.mdrequest-matching.mdsaved-requests.mdsecurity-context.mdsecurity-headers.mdservlet-integration.mdsession-management.md
tile.json

authorization.mddocs/

Authorization and Access Control

Authorization controls restrict access to resources based on authentication status, roles, and permissions.

Authorization Filter

AuthorizationFilter

The main authorization filter that applies access control to requests.

package org.springframework.security.web.access.intercept;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import java.io.IOException;

import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.access.intercept.AuthorizationFilter;
import org.springframework.web.filter.OncePerRequestFilter;

public class AuthorizationFilter extends OncePerRequestFilter {
    /**
     * Creates an authorization filter.
     *
     * @param authorizationManager the authorization manager to use
     */
    public AuthorizationFilter(AuthorizationManager<HttpServletRequest> authorizationManager);
    
    protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse,
                                    FilterChain chain) throws ServletException, IOException;
    
    /**
     * Sets the SecurityContextHolderStrategy.
     */
    public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy);
    
    /**
     * Sets the authorization event publisher.
     */
    public void setAuthorizationEventPublisher(AuthorizationEventPublisher eventPublisher);
    
    /**
     * Returns whether filter observes once per request (default: true).
     */
    public boolean isObserveOncePerRequest();
    
    /**
     * Sets whether to observe once per request.
     */
    public void setObserveOncePerRequest(boolean observeOncePerRequest);
    
    /**
     * Sets whether to filter error dispatches (default: true).
     */
    public void setFilterErrorDispatch(boolean filterErrorDispatch);
    
    /**
     * Sets whether to filter async dispatches (default: true).
     */
    public void setFilterAsyncDispatch(boolean filterAsyncDispatch);
}

RequestKey

Represents a key for caching authorization decisions.

package org.springframework.security.web.access.intercept;

public class RequestKey {
    public RequestKey(String url);
    
    public RequestKey(String url, String httpMethod);
    
    public boolean equals(Object obj);
    
    public int hashCode();
    
    public String toString();
}

RequestAuthorizationContext

HttpServletRequest authorization context used by AuthorizationManager implementations (Since 5.5).

package org.springframework.security.web.access.intercept;

import jakarta.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * An HttpServletRequest authorization context.
 */
public final class RequestAuthorizationContext {
    /**
     * Creates an instance with a request and no variables.
     *
     * @param request the HttpServletRequest to use
     */
    public RequestAuthorizationContext(HttpServletRequest request);

    /**
     * Creates an instance with a request and extracted variables.
     *
     * @param request the HttpServletRequest to use
     * @param variables map containing extracted variable names and values
     */
    public RequestAuthorizationContext(HttpServletRequest request, Map<String, String> variables);

    /**
     * Returns the HttpServletRequest.
     *
     * @return the HttpServletRequest
     */
    public HttpServletRequest getRequest();

    /**
     * Returns extracted variable values from request matchers.
     *
     * @return map of variable names to values
     */
    public Map<String, String> getVariables();
}

Access Denied Handling

AccessDeniedHandler

Interface for handling access denied failures.

package org.springframework.security.web.access;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

import org.springframework.security.access.AccessDeniedException;

public interface AccessDeniedHandler {
    /**
     * Handles an access denied failure.
     *
     * @param request the request
     * @param response the response
     * @param accessDeniedException the exception
     */
    void handle(HttpServletRequest request, HttpServletResponse response,
                AccessDeniedException accessDeniedException) throws IOException, ServletException;
}

AccessDeniedHandlerImpl

Default implementation that sends HTTP 403 or forwards to an error page.

package org.springframework.security.web.access;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

import org.springframework.security.access.AccessDeniedException;

public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
    public AccessDeniedHandlerImpl();
    
    /**
     * Sends HTTP 403 or forwards to error page.
     */
    public void handle(HttpServletRequest request, HttpServletResponse response,
                       AccessDeniedException accessDeniedException) throws IOException, ServletException;
    
    /**
     * Sets the error page to forward to. If null, sends HTTP 403.
     */
    public void setErrorPage(String errorPage);
}

NoOpAccessDeniedHandler

An AccessDeniedHandler that does nothing.

package org.springframework.security.web.access;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

import org.springframework.security.access.AccessDeniedException;

public class NoOpAccessDeniedHandler implements AccessDeniedHandler {
    public NoOpAccessDeniedHandler();

    public void handle(HttpServletRequest request, HttpServletResponse response,
                       AccessDeniedException accessDeniedException) throws IOException, ServletException;
}

HttpStatusAccessDeniedHandler

Returns a specific HTTP status code for access denied failures.

package org.springframework.security.web.access;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;

public class HttpStatusAccessDeniedHandler implements AccessDeniedHandler {
    /**
     * Creates a handler that returns the specified HTTP status.
     *
     * @param httpStatus the HTTP status to return (default: 403 Forbidden)
     */
    public HttpStatusAccessDeniedHandler(HttpStatus httpStatus);

    public void handle(HttpServletRequest request, HttpServletResponse response,
                       AccessDeniedException accessDeniedException) throws IOException, ServletException;
}

DelegatingAccessDeniedHandler

Delegates to different access denied handlers based on exception type.

package org.springframework.security.web.access;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.LinkedHashMap;

import org.springframework.security.access.AccessDeniedException;

public class DelegatingAccessDeniedHandler implements AccessDeniedHandler {
    /**
     * Creates a delegating handler.
     *
     * @param handlers map of exception types to handlers
     * @param defaultHandler handler used when no match is found
     */
    public DelegatingAccessDeniedHandler(
            LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler> handlers,
            AccessDeniedHandler defaultHandler);

    public void handle(HttpServletRequest request, HttpServletResponse response,
                       AccessDeniedException accessDeniedException) throws IOException, ServletException;
}

CompositeAccessDeniedHandler

Calls multiple access denied handlers in sequence.

package org.springframework.security.web.access;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

import org.springframework.security.access.AccessDeniedException;

public class CompositeAccessDeniedHandler implements AccessDeniedHandler {
    /**
     * Creates a composite handler with multiple delegates.
     *
     * @param accessDeniedHandlers the list of handlers to invoke
     */
    public CompositeAccessDeniedHandler(List<AccessDeniedHandler> accessDeniedHandlers);

    /**
     * Creates a composite handler with varargs delegates.
     *
     * @param accessDeniedHandlers the handlers to invoke
     */
    public CompositeAccessDeniedHandler(AccessDeniedHandler... accessDeniedHandlers);

    /**
     * Invokes all handlers in order. Stops if a handler throws an exception.
     */
    public void handle(HttpServletRequest request, HttpServletResponse response,
                       AccessDeniedException accessDeniedException) throws IOException, ServletException;
}

Exception Translation

ExceptionTranslationFilter

Handles AccessDeniedException and AuthenticationException thrown within the filter chain.

package org.springframework.security.web.access;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import java.io.IOException;

import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.util.ThrowableAnalyzer;
import org.springframework.web.filter.GenericFilterBean;

public class ExceptionTranslationFilter extends GenericFilterBean {
    /**
     * Creates a filter with the given authentication entry point.
     */
    public ExceptionTranslationFilter(AuthenticationEntryPoint authenticationEntryPoint);
    
    /**
     * Creates a filter with custom entry point and request cache.
     */
    public ExceptionTranslationFilter(AuthenticationEntryPoint authenticationEntryPoint,
                                       RequestCache requestCache);
    
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException;
    
    public AuthenticationEntryPoint getAuthenticationEntryPoint();
    
    /**
     * Sets the access denied handler.
     */
    public void setAccessDeniedHandler(AccessDeniedHandler accessDeniedHandler);
    
    /**
     * Sets the authentication trust resolver.
     */
    public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver);
    
    /**
     * Sets the throwable analyzer.
     */
    public void setThrowableAnalyzer(ThrowableAnalyzer throwableAnalyzer);
    
    public void setMessageSource(MessageSource messageSource);
    
    public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy);
    
    public void afterPropertiesSet();
}

Exception Translation Utilities

ThrowableAnalyzer

Analyzes throwable exceptions to extract root causes.

package org.springframework.security.web.util;

import java.util.List;

public class ThrowableAnalyzer {
    /**
     * Creates a throwable analyzer.
     */
    public ThrowableAnalyzer();

    /**
     * Determines the cause chain for the throwable.
     *
     * @param throwable the throwable to analyze
     * @return array of causes ordered from root to current
     */
    public final Throwable[] determineCauseChain(Throwable throwable);

    /**
     * Extracts the cause from a throwable.
     *
     * @param throwable the throwable
     * @return the cause or null
     */
    protected Throwable extractCause(Throwable throwable);

    /**
     * Initializes extractors for determining causes.
     */
    protected void initExtractorMap();

    /**
     * Registers a cause extractor for a throwable type.
     *
     * @param throwableType the throwable class
     * @param extractor the extractor
     */
    protected void registerExtractor(Class<? extends Throwable> throwableType,
                                      ThrowableCauseExtractor extractor);
}

ThrowableCauseExtractor

Extracts the cause from a throwable.

package org.springframework.security.web.util;

public interface ThrowableCauseExtractor {
    /**
     * Extracts the cause of a throwable.
     *
     * @param throwable the throwable
     * @return the cause or null
     */
    Throwable extractCause(Throwable throwable);
}

Web Invocation Privilege Evaluator

WebInvocationPrivilegeEvaluator

Allows checking whether users have access to specific URIs.

package org.springframework.security.web.access;

import org.springframework.security.core.Authentication;

public interface WebInvocationPrivilegeEvaluator {
    /**
     * Determines if the user has access to the given URI.
     *
     * @param uri the URI to check
     * @param authentication the authentication
     * @return true if access is allowed
     */
    boolean isAllowed(String uri, Authentication authentication);

    /**
     * Determines if the user has access to the URI with the given method.
     *
     * @param uri the URI to check
     * @param httpMethod the HTTP method (GET, POST, etc.)
     * @param authentication the authentication
     * @return true if access is allowed
     */
    boolean isAllowed(String uri, String httpMethod, Authentication authentication);

    /**
     * Determines if the user has access to the context-relative URI.
     *
     * @param contextPath the context path
     * @param uri the URI relative to context
     * @param httpMethod the HTTP method
     * @param authentication the authentication
     * @return true if access is allowed
     */
    boolean isAllowed(String contextPath, String uri, String httpMethod, Authentication authentication);
}

AuthorizationManagerWebInvocationPrivilegeEvaluator

AuthorizationManager-based implementation of WebInvocationPrivilegeEvaluator.

package org.springframework.security.web.access.intercept;

import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;

public class AuthorizationManagerWebInvocationPrivilegeEvaluator
        implements WebInvocationPrivilegeEvaluator {
    /**
     * Creates an evaluator with the given authorization manager.
     *
     * @param authorizationManager the authorization manager
     */
    public AuthorizationManagerWebInvocationPrivilegeEvaluator(
            AuthorizationManager<HttpServletRequest> authorizationManager);

    public boolean isAllowed(String uri, Authentication authentication);

    public boolean isAllowed(String uri, String httpMethod, Authentication authentication);

    public boolean isAllowed(String contextPath, String uri, String httpMethod,
                             Authentication authentication);
}

RequestMatcherDelegatingWebInvocationPrivilegeEvaluator

Delegates to different privilege evaluators based on request matchers.

package org.springframework.security.web.access.intercept;

import java.util.List;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
import org.springframework.security.web.util.matcher.RequestMatcher;

public final class RequestMatcherDelegatingWebInvocationPrivilegeEvaluator
        implements WebInvocationPrivilegeEvaluator {
    /**
     * Creates a delegating evaluator.
     *
     * @param delegates the list of matcher-evaluator pairs
     */
    public RequestMatcherDelegatingWebInvocationPrivilegeEvaluator(
            List<RequestMatcherEntry<WebInvocationPrivilegeEvaluator>> delegates);

    public boolean isAllowed(String uri, Authentication authentication);

    public boolean isAllowed(String uri, String httpMethod, Authentication authentication);

    public boolean isAllowed(String contextPath, String uri, String httpMethod,
                             Authentication authentication);

    /**
     * Pairs a request matcher with a privilege evaluator.
     */
    public static final class RequestMatcherEntry<T> {
        public RequestMatcherEntry(RequestMatcher requestMatcher, T entry);

        public RequestMatcher getRequestMatcher();

        public T getEntry();
    }
}

Authorization Managers

IpAddressAuthorizationManager

AuthorizationManager that checks IP addresses (Since 6.3).

package org.springframework.security.web.access;

import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.AuthorizationResult;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;

import java.util.function.Supplier;

public final class IpAddressAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {
    /**
     * Creates an authorization manager for the given IP address pattern.
     *
     * @param ipAddress IP address or CIDR notation (e.g., "192.168.1.0/24")
     */
    public static IpAddressAuthorizationManager hasIpAddress(String ipAddress);

    public AuthorizationResult authorize(Supplier<? extends Authentication> authentication,
                                         RequestAuthorizationContext requestAuthorizationContext);
}

RequestMatcherDelegatingAuthorizationManager

Delegates authorization to different managers based on request matchers (Since 5.5).

package org.springframework.security.web.access.intercept;

import java.util.List;

import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcherEntry;

import java.util.function.Supplier;

public final class RequestMatcherDelegatingAuthorizationManager
        implements AuthorizationManager<HttpServletRequest> {

    /**
     * Creates a builder for the delegating authorization manager.
     *
     * @return a new builder
     */
    public static Builder builder();

    public AuthorizationDecision check(Supplier<Authentication> authentication,
                                        HttpServletRequest request);

    /**
     * Builder for RequestMatcherDelegatingAuthorizationManager.
     */
    public static final class Builder {
        /**
         * Adds a mapping from RequestMatcher to AuthorizationManager.
         *
         * @param matcher the request matcher
         * @param manager the authorization manager
         * @return the builder
         */
        public Builder add(RequestMatcher matcher,
                          AuthorizationManager<RequestAuthorizationContext> manager);

        /**
         * Adds a list of RequestMatcherEntry mappings.
         *
         * @param mappings the list of mappings
         * @return the builder
         */
        public Builder mappings(List<RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>>> mappings);

        /**
         * Builds the RequestMatcherDelegatingAuthorizationManager.
         *
         * @return the authorization manager
         */
        public RequestMatcherDelegatingAuthorizationManager build();
    }
}

Request Transformation

PathPatternRequestTransformer

Transforms requests using path patterns (Since 6.4).

package org.springframework.security.web.access.intercept;

import jakarta.servlet.http.HttpServletRequest;

import org.springframework.web.util.pattern.PathPattern;

public final class PathPatternRequestTransformer {
    /**
     * Creates a transformer with a path pattern.
     *
     * @param pattern the path pattern
     */
    public PathPatternRequestTransformer(PathPattern pattern);

    /**
     * Transforms the request URI using the pattern.
     *
     * @param request the HTTP request
     * @return the transformed request URI
     */
    public String transform(HttpServletRequest request);
}

Expression-Based Access Control

WebSecurityExpressionRoot

Root object for Spring Security web expressions (hasRole, hasAuthority, etc.).

package org.springframework.security.web.access.expression;

import java.util.function.Supplier;

import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.context.support.RequestAuthorizationContext;

public class WebSecurityExpressionRoot extends SecurityExpressionRoot {
    /**
     * Creates a web security expression root.
     */
    public WebSecurityExpressionRoot(Supplier<Authentication> authentication,
                                      RequestAuthorizationContext requestAuthorizationContext);
    
    /**
     * Checks if the current user's IP address matches the pattern.
     *
     * @param ipAddress IP address or CIDR notation
     * @return true if IP matches
     */
    public boolean hasIpAddress(String ipAddress);
    
    public HttpServletRequest getRequest();
}

DefaultHttpSecurityExpressionHandler

Expression handler for web security expressions.

package org.springframework.security.web.access.expression;

import java.util.function.Supplier;

import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.context.support.RequestAuthorizationContext;

public class DefaultHttpSecurityExpressionHandler 
        implements SecurityExpressionHandler<RequestAuthorizationContext> {
    
    public DefaultHttpSecurityExpressionHandler();
    
    /**
     * Creates an evaluation context for the expression.
     */
    public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication,
                                                     RequestAuthorizationContext requestAuthorizationContext);
    
    /**
     * Sets the authentication trust resolver.
     */
    public void setTrustResolver(AuthenticationTrustResolver trustResolver);
    
    /**
     * Sets the default role prefix (default: "ROLE_").
     */
    public void setDefaultRolePrefix(String defaultRolePrefix);
}

WebExpressionAuthorizationManager

AuthorizationManager that uses Spring EL expressions (Since 5.5).

package org.springframework.security.web.access.expression;

import org.springframework.expression.Expression;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;

import java.util.function.Supplier;

public final class WebExpressionAuthorizationManager
        implements AuthorizationManager<RequestAuthorizationContext> {
    /**
     * Creates an authorization manager from a SpEL expression.
     *
     * @param expressionString the SpEL expression (e.g., "hasRole('ADMIN')")
     */
    public WebExpressionAuthorizationManager(String expressionString);

    public AuthorizationDecision check(Supplier<Authentication> authentication,
                                        RequestAuthorizationContext context);

    /**
     * Sets the expression handler.
     *
     * @param expressionHandler the expression handler
     */
    public void setExpressionHandler(SecurityExpressionHandler<RequestAuthorizationContext> expressionHandler);
}

EvaluationContextPostProcessor

Post-processes evaluation contexts for expression-based authorization.

package org.springframework.security.access.expression;

import org.springframework.expression.EvaluationContext;

public interface EvaluationContextPostProcessor<T> {
    /**
     * Post-processes the evaluation context.
     *
     * @param context the evaluation context
     * @param object the invocation object
     * @return the processed evaluation context
     */
    EvaluationContext postProcess(EvaluationContext context, T object);
}

AbstractVariableEvaluationContextPostProcessor

Base class for post-processors that add variables to evaluation contexts.

package org.springframework.security.access.expression;

import org.springframework.expression.EvaluationContext;

public abstract class AbstractVariableEvaluationContextPostProcessor<T>
        implements EvaluationContextPostProcessor<T> {
    /**
     * Creates a variable evaluation context post-processor.
     */
    public AbstractVariableEvaluationContextPostProcessor();

    public final EvaluationContext postProcess(EvaluationContext context, T object);

    /**
     * Gets the name of the variable to add.
     *
     * @return the variable name
     */
    protected abstract String getVariableName();

    /**
     * Gets the value of the variable to add.
     *
     * @param object the invocation object
     * @return the variable value
     */
    protected abstract Object getVariableValue(T object);
}

Usage Examples

Basic Authorization Configuration

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class AuthorizationConfig {
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/public/**").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
            );
        
        return http.build();
    }
}

Expression-Based Authorization

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class ExpressionAuthorizationConfig {
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/admin/**")
                    .access("hasRole('ADMIN') and hasIpAddress('192.168.1.0/24')")
                .requestMatchers("/api/**")
                    .access("hasAuthority('API_ACCESS') or hasRole('API_USER')")
                .requestMatchers("/user/{username}/**")
                    .access("@webSecurity.checkUserId(authentication, #username)")
                .anyRequest().authenticated()
            );
        
        return http.build();
    }
}

Custom Access Denied Handler

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;

public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
                       AccessDeniedException accessDeniedException) throws IOException {
        
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.setContentType("application/json");
        
        String json = String.format(
            "{\"error\": \"Access Denied\", \"message\": \"%s\", \"path\": \"%s\"}",
            accessDeniedException.getMessage(),
            request.getRequestURI()
        );
        
        response.getWriter().write(json);
    }
}

// Configuration
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .exceptionHandling(handling -> handling
            .accessDeniedHandler(new CustomAccessDeniedHandler())
        );
    return http.build();
}

Programmatic Access Checking

import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
import org.springframework.security.core.Authentication;

@Service
public class SecurityService {
    
    private final WebInvocationPrivilegeEvaluator privilegeEvaluator;
    
    public SecurityService(WebInvocationPrivilegeEvaluator privilegeEvaluator) {
        this.privilegeEvaluator = privilegeEvaluator;
    }
    
    public boolean canAccessAdminPage(Authentication authentication) {
        return privilegeEvaluator.isAllowed("/admin", authentication);
    }
    
    public boolean canModifyResource(Authentication authentication, String resourceId) {
        String uri = "/api/resources/" + resourceId;
        return privilegeEvaluator.isAllowed(uri, "PUT", authentication);
    }
}

Multiple Security Filter Chains with Different Authorization

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;

@Configuration
public class MultiChainAuthorizationConfig {
    
    // API endpoints - stateless, token-based
    @Bean
    @Order(1)
    public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
        http
            .securityMatchers(matchers -> matchers
                .requestMatchers(PathPatternRequestMatcher.pathPattern("/api/**"))
            )
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .requestMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2.jwt());
        
        return http.build();
    }
    
    // Web endpoints - session-based
    @Bean
    @Order(2)
    public SecurityFilterChain webFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/public/**", "/login", "/register").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .requestMatchers("/user/**").hasRole("USER")
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .defaultSuccessUrl("/dashboard")
            )
            .logout(logout -> logout
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login?logout")
            );
        
        return http.build();
    }
}

Custom Authorization Manager with Request Context

import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;

import java.util.function.Supplier;

public class TimeBasedAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {
    
    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication,
                                       RequestAuthorizationContext context) {
        
        Authentication auth = authentication.get();
        if (auth == null || !auth.isAuthenticated()) {
            return new AuthorizationDecision(false);
        }
        
        HttpServletRequest request = context.getRequest();
        String path = request.getRequestURI();
        
        // Restrict admin access to business hours (9 AM - 5 PM)
        if (path.startsWith("/admin/")) {
            int hour = java.time.LocalTime.now().getHour();
            if (hour < 9 || hour >= 17) {
                return new AuthorizationDecision(false);
            }
        }
        
        // Extract path variables for resource-based authorization
        Map<String, String> variables = context.getVariables();
        String userId = variables.get("userId");
        
        if (userId != null && !auth.getName().equals(userId)) {
            // Users can only access their own resources
            return new AuthorizationDecision(false);
        }
        
        return new AuthorizationDecision(true);
    }
}

// Configuration
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(authorize -> authorize
            .requestMatchers("/user/{userId}/**")
                .access(new AuthorizationManagerRequestMatcherRegistry.RequestMatcherEntry(
                    PathPatternRequestMatcher.pathPattern("/user/{userId}/**"),
                    new TimeBasedAuthorizationManager()
                ))
            .anyRequest().authenticated()
        );
    return http.build();
}

Handling Authorization Failures with Custom Logic

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

public class SmartAccessDeniedHandler implements AccessDeniedHandler {
    
    private final AuditService auditService;
    
    public SmartAccessDeniedHandler(AuditService auditService) {
        this.auditService = auditService;
    }
    
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
                       AccessDeniedException accessDeniedException) throws IOException {
        
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        
        // Log access denied attempt
        auditService.logAccessDenied(
            auth != null ? auth.getName() : "anonymous",
            request.getRequestURI(),
            request.getMethod(),
            request.getRemoteAddr()
        );
        
        // Different handling based on user type
        if (auth != null && auth.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_PREMIUM"))) {
            // Premium users get helpful error message
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.setContentType("application/json");
            response.getWriter().write(
                "{\"error\": \"Access Denied\", \"message\": \"Upgrade required for this feature\"}"
            );
        } else if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
            // AJAX requests get JSON response
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.setContentType("application/json");
            response.getWriter().write(
                "{\"error\": \"Access Denied\", \"path\": \"" + request.getRequestURI() + "\"}"
            );
        } else {
            // Regular requests redirect to access denied page
            response.sendRedirect("/access-denied");
        }
    }
}