Authorization controls restrict access to resources based on authentication status, roles, and permissions.
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);
}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();
}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();
}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;
}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);
}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;
}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;
}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;
}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;
}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();
}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);
}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);
}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);
}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);
}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();
}
}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);
}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();
}
}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);
}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();
}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);
}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);
}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);
}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);
}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();
}
}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();
}
}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();
}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);
}
}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();
}
}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();
}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");
}
}
}