# Authorize HttpServletRequests with AuthorizationFilter
This section builds on Servlet Architecture and Implementation by digging deeper into how authorization works within Servlet-based applications.
AuthorizationFilter supersedes FilterSecurityInterceptor .To remain backward compatible, FilterSecurityInterceptor remains the default.This section discusses how AuthorizationFilter works and how to override the default configuration. |
---|
The AuthorizationFilter
(opens new window) provides authorization for HttpServletRequest
s.
It is inserted into the FilterChainProxy as one of the Security Filters.
You can override the default when you declare a SecurityFilterChain
.
Instead of using authorizeRequests
, use authorizeHttpRequests
, like so:
Example 1. Use authorizeHttpRequests
Java
@Bean
SecurityFilterChain web(HttpSecurity http) throws AuthenticationException {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated();
)
// ...
return http.build();
}
This improves on authorizeRequests
in a number of ways:
Uses the simplified
AuthorizationManager
API instead of metadata sources, config attributes, decision managers, and voters. This simplifies reuse and customization.Delays
Authentication
lookup. Instead of the authentication needing to be looked up for every request, it will only look it up in requests where an authorization decision requires authentication.Bean-based configuration support.
When authorizeHttpRequests
is used instead of authorizeRequests
, then AuthorizationFilter
(opens new window) is used instead of FilterSecurityInterceptor
.
Figure 1. Authorize HttpServletRequest
First, the
AuthorizationFilter
obtains an Authentication from the SecurityContextHolder. It wraps this in anSupplier
in order to delay lookup.Second,
AuthorizationFilter
creates aFilterInvocation
(opens new window) from theHttpServletRequest
,HttpServletResponse
, andFilterChain
.Next, it passes the
Supplier<Authentication>
andFilterInvocation
to theAuthorizationManager
.If authorization is denied, an
AccessDeniedException
is thrown. In this case theExceptionTranslationFilter
handles theAccessDeniedException
.If access is granted,
AuthorizationFilter
continues with the FilterChain which allows the application to process normally.
We can configure Spring Security to have different rules by adding more rules in order of precedence.
Example 2. Authorize Requests
Java
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
http
// ...
.authorizeHttpRequests(authorize -> authorize (1)
.mvcMatchers("/resources/**", "/signup", "/about").permitAll() (2)
.mvcMatchers("/admin/**").hasRole("ADMIN") (3)
.mvcMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')") (4)
.anyRequest().denyAll() (5)
);
return http.build();
}
1 | There are multiple authorization rules specified. Each rule is considered in the order they were declared. |
---|---|
2 | We specified multiple URL patterns that any user can access. Specifically, any user can access a request if the URL starts with "/resources/", equals "/signup", or equals "/about". |
3 | Any URL that starts with "/admin/" will be restricted to users who have the role "ROLE_ADMIN". You will notice that since we are invoking the hasRole method we do not need to specify the "ROLE_" prefix. |
4 | Any URL that starts with "/db/" requires the user to have both "ROLE_ADMIN" and "ROLE_DBA". You will notice that since we are using the hasRole expression we do not need to specify the "ROLE_" prefix. |
5 | Any URL that has not already been matched on is denied access. This is a good strategy if you do not want to accidentally forget to update your authorization rules. |
You can take a bean-based approach by constructing your own RequestMatcherDelegatingAuthorizationManager
like so:
Example 3. Configure RequestMatcherDelegatingAuthorizationManager
Java
@Bean
SecurityFilterChain web(HttpSecurity http, AuthorizationManager<RequestAuthorizationContext> access)
throws AuthenticationException {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().access(access)
)
// ...
return http.build();
}
@Bean
AuthorizationManager<RequestAuthorizationContext> requestMatcherAuthorizationManager(HandlerMappingIntrospector introspector) {
RequestMatcher permitAll =
new AndRequestMatcher(
new MvcRequestMatcher(introspector, "/resources/**"),
new MvcRequestMatcher(introspector, "/signup"),
new MvcRequestMatcher(introspector, "/about"));
RequestMatcher admin = new MvcRequestMatcher(introspector, "/admin/**");
RequestMatcher db = new MvcRequestMatcher(introspector, "/db/**");
RequestMatcher any = AnyRequestMatcher.INSTANCE;
AuthorizationManager<HttpRequestServlet> manager = RequestMatcherDelegatingAuthorizationManager.builder()
.add(permitAll, (context) -> new AuthorizationDecision(true))
.add(admin, AuthorityAuthorizationManager.hasRole("ADMIN"))
.add(db, AuthorityAuthorizationManager.hasRole("DBA"))
.add(any, new AuthenticatedAuthorizationManager())
.build();
return (context) -> manager.check(context.getRequest());
}
You can also wire your own custom authorization managers for any request matcher.
Here is an example of mapping a custom authorization manager to the my/authorized/endpoint
:
Example 4. Custom Authorization Manager
Java
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.mvcMatchers("/my/authorized/endpoint").access(new CustomAuthorizationManager());
)
// ...
return http.build();
}
Or you can provide it for all requests as seen below:
Example 5. Custom Authorization Manager for All Requests
Java
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest.access(new CustomAuthorizationManager());
)
// ...
return http.build();
}
Authorization ArchitectureAuthorize HTTP Requests with FilterSecurityInterceptor