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

filter-chain.mddocs/

Filter Chain Infrastructure

The filter chain infrastructure is the foundation of Spring Security Web, managing the security filter chain that processes HTTP requests.

Key Information for Agents

Required Dependencies:

  • spring-security-web (this package)
  • spring-security-core is required (provides SecurityContextHolderStrategy, AuthenticationException)
  • spring-security-config is required for HttpSecurity DSL and SecurityFilterChain bean creation
  • Jakarta Servlet API required for Filter interface
  • Spring Web required for GenericFilterBean and OncePerRequestFilter

Default Behaviors:

  • Default firewall: StrictHttpFirewall (rejects suspicious requests)
  • Default request rejected handler: DefaultRequestRejectedHandler (rethrows exception)
  • Filter chain matching: First matching SecurityFilterChain is used (order matters)
  • Multiple filter chains: Evaluated in order until one matches
  • Filter chain decorator: None by default (can add ObservationFilterChainDecorator for metrics)
  • Redirect strategy: DefaultRedirectStrategy with HTTP 302 status
  • Port mapper: PortMapperImpl with default mappings (80:443, 8080:8443)
  • Authentication entry point: LoginUrlAuthenticationEntryPoint (redirects to /login)

Threading Model:

  • FilterChainProxy.doFilter() executes on servlet container thread (synchronous)
  • Filter chain matching is sequential (first match wins)
  • Each filter in chain executes in same thread
  • SecurityFilterChain.matches() called for each chain until match found
  • Filter chain decorators wrap the chain but don't change threading model
  • Request rejected handler executes synchronously in filter chain thread

Lifecycle:

  • FilterChainProxy implements Filter (registered in servlet container via FilterRegistrationBean)
  • SecurityFilterChain beans are discovered and collected at application startup
  • Filter chains are immutable after creation (cannot modify filters at runtime)
  • FilterChainProxy.afterPropertiesSet() validates filter chain configuration
  • Filter chain validator can reject invalid configurations at startup
  • Filter chain decorator is applied once per filter chain (not per request)

Exceptions:

  • RequestRejectedException - Firewall rejects request (wrapped by request rejected handler)
  • UnreachableFilterChainException - Filter chain configuration error (chain cannot be reached)
  • ServletException, IOException - Standard servlet exceptions from filter processing
  • IllegalArgumentException - Invalid filter chain configuration

Edge Cases:

  • Multiple SecurityFilterChain beans: Order matters, first matching chain is used
  • No matching filter chain: Request proceeds without security filters (security disabled)
  • Filter chain with no filters: Valid but provides no security (empty chain)
  • Custom filter chain decorator: Applied to entire chain, not individual filters
  • Port mapper: Only used when forceHttps=true in LoginUrlAuthenticationEntryPoint
  • Redirect strategy: Context-relative redirects use setContextRelative(true)
  • Filter chain validator: Can prevent application startup if configuration is invalid
  • Request rejected handler: Must handle RequestRejectedException or application will fail
  • Filter chain order: More specific matchers should come before general ones (e.g., /api/** before /**)

Core Components

FilterChainProxy

FilterChainProxy is the central entry point that delegates Filter requests to Spring-managed security filter chains.

package org.springframework.security.web;

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

import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.security.web.firewall.RequestRejectedHandler;
import org.springframework.web.filter.GenericFilterBean;

public class FilterChainProxy extends GenericFilterBean {
    /**
     * Creates an empty FilterChainProxy with no filter chains.
     */
    public FilterChainProxy();

    /**
     * Creates a FilterChainProxy with a single security filter chain.
     *
     * @param chain the SecurityFilterChain instance
     */
    public FilterChainProxy(SecurityFilterChain chain);

    /**
     * Creates a FilterChainProxy with the given security filter chains.
     *
     * @param filterChains the list of SecurityFilterChain instances
     */
    public FilterChainProxy(List<SecurityFilterChain> filterChains);
    
    /**
     * Delegates the request through the matching security filter chain.
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException;
    
    /**
     * Sets the HttpFirewall for request validation.
     * Default is StrictHttpFirewall.
     */
    public void setFirewall(HttpFirewall firewall);
    
    /**
     * Sets the handler for rejected requests.
     */
    public void setRequestRejectedHandler(RequestRejectedHandler requestRejectedHandler);
    
    /**
     * Sets the SecurityContextHolderStrategy.
     */
    public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy);
    
    /**
     * Sets a validator for the filter chain configuration.
     */
    public void setFilterChainValidator(FilterChainValidator filterChainValidator);
    
    /**
     * Sets a decorator for customizing the filter chain execution.
     */
    public void setFilterChainDecorator(FilterChainDecorator filterChainDecorator);

    /**
     * Returns the list of SecurityFilterChains which will be matched against
     * and applied to incoming requests.
     *
     * @return unmodifiable list of SecurityFilterChain instances
     */
    public List<SecurityFilterChain> getFilterChains();

    /**
     * Convenience method for getting filters for a specific URL, mainly for testing.
     *
     * @param url the URL to match
     * @return list of Filter instances or null if no chain matches
     */
    public List<Filter> getFilters(String url);

    public void afterPropertiesSet();

    public String toString();
}

SecurityFilterChain

SecurityFilterChain defines a filter chain capable of matching requests and providing filters.

package org.springframework.security.web;

import jakarta.servlet.Filter;
import jakarta.servlet.http.HttpServletRequest;
import java.util.List;

public interface SecurityFilterChain {
    /**
     * Determines if this filter chain applies to the given request.
     *
     * @param request the HttpServletRequest to match
     * @return true if this filter chain should process the request
     */
    boolean matches(HttpServletRequest request);
    
    /**
     * Returns the list of filters to be applied.
     *
     * @return the ordered list of Filter instances
     */
    List<Filter> getFilters();
}

DefaultSecurityFilterChain

Standard implementation of SecurityFilterChain (Since 3.1).

package org.springframework.security.web;

import jakarta.servlet.Filter;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.web.util.matcher.RequestMatcher;
import java.util.List;

/**
 * Standard implementation of SecurityFilterChain.
 */
public final class DefaultSecurityFilterChain implements SecurityFilterChain {
    /**
     * Creates a DefaultSecurityFilterChain with a RequestMatcher and filters.
     *
     * @param requestMatcher the matcher to determine if this chain applies
     * @param filters the filters to be applied (varargs)
     */
    public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters);

    /**
     * Creates a DefaultSecurityFilterChain with a RequestMatcher and a list of filters.
     *
     * @param requestMatcher the matcher to determine if this chain applies
     * @param filters the list of filters to be applied
     */
    public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters);

    /**
     * Returns the RequestMatcher used by this filter chain.
     *
     * @return the RequestMatcher instance
     */
    public RequestMatcher getRequestMatcher();

    /**
     * Returns the list of filters in this chain.
     *
     * @return the ordered list of Filter instances
     */
    public List<Filter> getFilters();

    /**
     * Determines if this filter chain applies to the given request.
     *
     * @param request the HttpServletRequest to match
     * @return true if this filter chain should process the request
     */
    public boolean matches(HttpServletRequest request);
}

FilterInvocation

FilterInvocation holds HTTP filter-related objects and provides request information.

package org.springframework.security.web;

import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class FilterInvocation {
    /**
     * Creates a FilterInvocation from actual servlet objects.
     *
     * @param request the ServletRequest
     * @param response the ServletResponse
     * @param chain the FilterChain
     */
    public FilterInvocation(ServletRequest request, ServletResponse response, FilterChain chain);
    
    public FilterChain getChain();
    
    public String getFullRequestUrl();
    
    public HttpServletRequest getHttpRequest();
    
    public HttpServletResponse getHttpResponse();
    
    public String getRequestUrl();
    
    public HttpServletRequest getRequest();
    
    public HttpServletResponse getResponse();
    
    public String getCharacterEncoding();
    
    public String getContextPath();
    
    public String toString();
}

RequestMatcherRedirectFilter

Utility filter that redirects requests matching a RequestMatcher to a specified URL (Since 5.6).

package org.springframework.security.web;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;

/**
 * Filter that redirects requests that match RequestMatcher to the specified URL.
 */
public final class RequestMatcherRedirectFilter extends OncePerRequestFilter {
    /**
     * Creates a RequestMatcherRedirectFilter.
     *
     * @param requestMatcher the request matcher to determine which requests to redirect
     * @param redirectUrl the URL to redirect to
     */
    public RequestMatcherRedirectFilter(RequestMatcher requestMatcher, String redirectUrl);

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException;
}

Authentication Entry Points

AuthenticationEntryPoint

AuthenticationEntryPoint commences an authentication scheme when authentication is required.

package org.springframework.security.web;

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

import org.springframework.security.core.AuthenticationException;

public interface AuthenticationEntryPoint {
    /**
     * Commences an authentication scheme.
     * Called by ExceptionTranslationFilter when authentication is required.
     *
     * @param request the request during which authentication failed
     * @param response the response
     * @param authException the exception that caused authentication to fail
     */
    void commence(HttpServletRequest request, HttpServletResponse response,
                  AuthenticationException authException) throws IOException, ServletException;
}

LoginUrlAuthenticationEntryPoint

Redirects to a login page when authentication is required.

package org.springframework.security.web.authentication;

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

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.PortMapper;
import org.springframework.security.web.RedirectStrategy;

public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoint {
    /**
     * Creates an entry point with the specified login form URL.
     *
     * @param loginFormUrl the URL of the login page
     */
    public LoginUrlAuthenticationEntryPoint(String loginFormUrl);
    
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException) throws IOException, ServletException;
    
    /**
     * Forces HTTPS for the login page.
     */
    public void setForceHttps(boolean forceHttps);
    
    /**
     * Sets the PortMapper for HTTP to HTTPS redirection.
     */
    public void setPortMapper(PortMapper portMapper);
    
    /**
     * Uses forward instead of redirect to login page.
     */
    public void setUseForward(boolean useForward);
    
    /**
     * Enables relative URIs in redirects.
     */
    public void setFavorRelativeUris(boolean favorRelativeUris);
    
    public String getLoginFormUrl();
    
    public int getServerPort(ServletRequest request);
    
    public void afterPropertiesSet();
}

Http403ForbiddenEntryPoint

Returns HTTP 403 Forbidden for pre-authenticated scenarios.

package org.springframework.security.web.authentication;

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

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

public class Http403ForbiddenEntryPoint implements AuthenticationEntryPoint {
    public Http403ForbiddenEntryPoint();
    
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException arg2) throws IOException, ServletException;
}

DelegatingAuthenticationEntryPoint

Selects an AuthenticationEntryPoint based on RequestMatcher evaluation.

package org.springframework.security.web.authentication;

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.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.RequestMatcher;

public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPoint {
    /**
     * Creates a delegating entry point with RequestMatcher to EntryPoint mappings.
     *
     * @param entryPoints map of RequestMatcher to AuthenticationEntryPoint
     */
    public DelegatingAuthenticationEntryPoint(
            LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints);
    
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException) throws IOException, ServletException;
    
    /**
     * Sets the default entry point when no matcher matches.
     */
    public void setDefaultEntryPoint(AuthenticationEntryPoint defaultEntryPoint);
    
    public void afterPropertiesSet();
    
    /**
     * Creates a builder for configuring entry points.
     */
    public static Builder builder();
}
package org.springframework.security.web.authentication;

import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.RequestMatcher;

public static final class DelegatingAuthenticationEntryPoint.Builder {
    /**
     * Sets the default entry point.
     */
    public Builder defaultEntryPoint(AuthenticationEntryPoint defaultEntryPoint);
    
    /**
     * Adds an entry point for the given request matcher.
     */
    public Builder addEntryPointFor(AuthenticationEntryPoint entryPoint, RequestMatcher requestMatcher);
    
    /**
     * Builds the DelegatingAuthenticationEntryPoint.
     */
    public AuthenticationEntryPoint build();
}

NoOpAuthenticationEntryPoint

An AuthenticationEntryPoint that does nothing.

package org.springframework.security.web.authentication;

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

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

public class NoOpAuthenticationEntryPoint implements AuthenticationEntryPoint {
    public NoOpAuthenticationEntryPoint();
    
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException) throws IOException, ServletException;
}

Filter Chain Decorators

FilterChainDecorator

Interface for decorating filter chain execution.

package org.springframework.security.web;

import jakarta.servlet.FilterChain;

public interface FilterChainDecorator {
    /**
     * Decorates the filter chain with additional behavior.
     *
     * @param filterChain the original filter chain
     * @return the decorated filter chain
     */
    FilterChain decorate(FilterChain filterChain);
}

ObservationFilterChainDecorator

Decorates filter chain with observability support using Micrometer.

package org.springframework.security.web;

import io.micrometer.observation.ObservationRegistry;
import jakarta.servlet.FilterChain;

public class ObservationFilterChainDecorator implements FilterChainDecorator {
    /**
     * Creates a decorator with the given observation registry.
     *
     * @param observationRegistry the Micrometer observation registry
     */
    public ObservationFilterChainDecorator(ObservationRegistry observationRegistry);

    public FilterChain decorate(FilterChain filterChain);
}

Constants and Attributes

WebAttributes

Constants for storing security-related attributes in request/session scope.

package org.springframework.security.web;

public final class WebAttributes {
    /**
     * Attribute for storing authentication exception.
     */
    public static final String AUTHENTICATION_EXCEPTION =
        "SPRING_SECURITY_LAST_EXCEPTION";

    /**
     * Attribute for storing access denied exception.
     */
    public static final String ACCESS_DENIED_403 =
        "SPRING_SECURITY_403_EXCEPTION";

    /**
     * Attribute for storing web invocation privilege evaluator.
     */
    public static final String WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE =
        "org.springframework.security.web.access.WebInvocationPrivilegeEvaluator.CONTEXT_ATTRIBUTE";
}

Redirect Strategy

RedirectStrategy

Interface for redirection logic.

package org.springframework.security.web;

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

public interface RedirectStrategy {
    /**
     * Performs a redirect to the supplied URL.
     *
     * @param request the current request
     * @param response the response to redirect
     * @param url the target URL
     */
    void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
            throws IOException;
}

DefaultRedirectStrategy

Default implementation of RedirectStrategy.

package org.springframework.security.web;

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

import org.springframework.http.HttpStatus;

public class DefaultRedirectStrategy implements RedirectStrategy {
    public DefaultRedirectStrategy();
    
    public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
            throws IOException;
    
    /**
     * Makes the redirect URL relative to the context path.
     */
    public void setContextRelative(boolean useRelativeContext);
    
    /**
     * Sets the HTTP status code for redirects (default: 302).
     */
    public void setStatusCode(HttpStatus statusCode);
}

Port Mapping

PortMapper

Maps HTTP ports to HTTPS ports for secure redirects.

package org.springframework.security.web;

import jakarta.servlet.ServletRequest;

public interface PortMapper {
    /**
     * Locates the HTTP port for the given HTTPS port.
     *
     * @param httpsPort the HTTPS port
     * @return the corresponding HTTP port, or null if unknown
     */
    Integer lookupHttpPort(Integer httpsPort);
    
    /**
     * Locates the HTTPS port for the given HTTP port.
     *
     * @param httpPort the HTTP port
     * @return the corresponding HTTPS port, or null if unknown
     */
    Integer lookupHttpsPort(Integer httpPort);
}

PortMapperImpl

Default PortMapper implementation with configurable mappings.

package org.springframework.security.web;

import java.util.Map;

public class PortMapperImpl implements PortMapper {
    public PortMapperImpl();
    
    public Integer lookupHttpPort(Integer httpsPort);
    
    public Integer lookupHttpsPort(Integer httpPort);
    
    /**
     * Sets custom port mappings. Keys are String HTTP ports, values are String HTTPS ports.
     * Default mappings are 80:443 and 8080:8443.
     *
     * @param newMappings map of HTTP to HTTPS port mappings
     */
    public void setPortMappings(Map<String, String> newMappings);
}

Exceptions

UnreachableFilterChainException

Thrown when a SecurityFilterChain cannot be reached due to configuration issues.

package org.springframework.security.web;

public class UnreachableFilterChainException extends IllegalArgumentException {
    /**
     * Creates an exception with the specified message.
     *
     * @param message the detail message
     */
    public UnreachableFilterChainException(String message);
    
    /**
     * Creates an exception with filter chain details.
     *
     * @param message the detail message
     * @param filterChain the filter chain that caused the issue
     * @param unreachableFilterChain the unreachable filter chain
     */
    public UnreachableFilterChainException(String message, SecurityFilterChain filterChain,
                                           SecurityFilterChain unreachableFilterChain);
    
    public SecurityFilterChain getFilterChain();
    
    public SecurityFilterChain getUnreachableFilterChain();
}

Usage Examples

Basic Filter Chain 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 SecurityConfig {

    @Bean
    public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
        http
            .securityMatchers(matchers -> matchers
                .requestMatchers("/api/**")
            )
            .authorizeHttpRequests(authorize -> authorize
                .anyRequest().authenticated()
            )
            .httpBasic(Customizer.withDefaults());

        return http.build();
    }

    @Bean
    public SecurityFilterChain webFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .permitAll()
            );
        
        return http.build();
    }
}

Custom Authentication Entry Point

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException) throws IOException {
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().write("{\"error\": \"Authentication required\"}");
    }
}

// Configure in security chain
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .exceptionHandling(handling -> handling
            .authenticationEntryPoint(new CustomAuthenticationEntryPoint())
        );
    return http.build();
}

Delegating Entry Point

import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;

@Bean
public AuthenticationEntryPoint delegatingEntryPoint() {
    return DelegatingAuthenticationEntryPoint.builder()
        .addEntryPointFor(
            new Http403ForbiddenEntryPoint(),
            PathPatternRequestMatcher.pathPattern("/api/**")
        )
        .addEntryPointFor(
            new LoginUrlAuthenticationEntryPoint("/login"),
            PathPatternRequestMatcher.pathPattern("/admin/**")
        )
        .defaultEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
        .build();
}

Custom Filter Chain with Observability

import org.springframework.security.web.FilterChainDecorator;
import org.springframework.security.web.ObservationFilterChainDecorator;
import io.micrometer.observation.ObservationRegistry;
import jakarta.servlet.FilterChain;

@Configuration
public class ObservableSecurityConfig {
    
    @Bean
    public FilterChainProxy filterChainProxy(List<SecurityFilterChain> filterChains,
                                              ObservationRegistry observationRegistry) {
        FilterChainProxy proxy = new FilterChainProxy(filterChains);
        
        // Add observability support
        proxy.setFilterChainDecorator(
            new ObservationFilterChainDecorator(observationRegistry)
        );
        
        return proxy;
    }
}

Multiple Filter Chains with Different Priorities

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 MultiChainConfig {
    
    // High priority: API endpoints
    @Bean
    @Order(1)
    public SecurityFilterChain apiChain(HttpSecurity http) throws Exception {
        http
            .securityMatchers(matchers -> matchers
                .requestMatchers(PathPatternRequestMatcher.pathPattern("/api/**"))
            )
            .authorizeHttpRequests(authorize -> authorize
                .anyRequest().authenticated()
            )
            .httpBasic(basic -> {})
            .csrf(csrf -> csrf.disable());
        
        return http.build();
    }
    
    // Lower priority: Web endpoints
    @Bean
    @Order(2)
    public SecurityFilterChain webChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
            );
        
        return http.build();
    }
}

Custom Request Rejected Handler

import org.springframework.security.web.firewall.RequestRejectedException;
import org.springframework.security.web.firewall.RequestRejectedHandler;

public class LoggingRequestRejectedHandler implements RequestRejectedHandler {
    
    private final Logger logger = LoggerFactory.getLogger(getClass());
    
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
                       RequestRejectedException requestRejectedException) 
            throws IOException, ServletException {
        
        logger.warn("Request rejected: {} {} from {} - {}",
            request.getMethod(),
            request.getRequestURI(),
            request.getRemoteAddr(),
            requestRejectedException.getMessage()
        );
        
        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
        response.setContentType("application/json");
        response.getWriter().write(
            "{\"error\": \"Invalid request\", \"message\": \"" + 
            requestRejectedException.getMessage() + "\"}"
        );
    }
}

// Configuration
@Bean
public FilterChainProxy filterChainProxy(List<SecurityFilterChain> filterChains) {
    FilterChainProxy proxy = new FilterChainProxy(filterChains);
    proxy.setRequestRejectedHandler(new LoggingRequestRejectedHandler());
    return proxy;
}