There is a newer version available. Please update to Spring Security 5.6! |
Authorize HttpServletRequest with FilterSecurityInterceptor
This section builds on Servlet Architecture and Implementation by digging deeper into how authorization works within Servlet based applications.
The {security-api-url}org/springframework/security/web/access/intercept/FilterSecurityInterceptor.html[FilterSecurityInterceptor
] provides authorization for HttpServletRequest
s.
It is inserted into the [servlet-filterchainproxy] as one of the [servlet-security-filters].
-
First, the
FilterSecurityInterceptor
obtains an [servlet-authentication-authentication] from the [servlet-authentication-securitycontextholder]. -
Second,
FilterSecurityInterceptor
creates a {security-api-url}org/springframework/security/web/FilterInvocation.html[FilterInvocation
] from theHttpServletRequest
,HttpServletResponse
, andFilterChain
that are passed into theFilterSecurityInterceptor
. -
Next, it passes the
FilterInvocation
toSecurityMetadataSource
to get theConfigAttribute
s. -
Finally, it passes the
Authentication
,FilterInvocation
, andConfigAttribute
s to theAccessDecisionManager
.-
If authorization is denied, an
AccessDeniedException
is thrown. In this case theExceptionTranslationFilter
handles theAccessDeniedException
. -
If access is granted,
FilterSecurityInterceptor
continues with the FilterChain which allows the application to process normally.
-
By default, Spring Security’s authorization will require all requests to be authenticated. The explicit configuration looks like:
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.authorizeRequests(authorize -> authorize
.anyRequest().authenticated()
);
}
<http>
<!-- ... -->
<intercept-url pattern="/**" access="authenticated"/>
</http>
fun configure(http: HttpSecurity) {
http {
// ...
authorizeRequests {
authorize(anyRequest, authenticated)
}
}
}
We can configure Spring Security to have different rules by adding more rules in order of precedence.
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.authorizeRequests(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)
);
}
<http> (1)
<!-- ... -->
(2)
<intercept-url pattern="/resources/**" access="permitAll"/>
<intercept-url pattern="/signup" access="permitAll"/>
<intercept-url pattern="/about" access="permitAll"/>
<intercept-url pattern="/admin/**" access="hasRole('ADMIN')"/> (3)
<intercept-url pattern="/db/**" access="hasRole('ADMIN') and hasRole('DBA')"/> (4)
<intercept-url pattern="/**" access="denyAll"/> (5)
</http>
fun configure(http: HttpSecurity) {
http {
authorizeRequests { (1)
authorize("/resources/**", permitAll) (2)
authorize("/signup", permitAll)
authorize("/about", permitAll)
authorize("/admin/**", hasRole("ADMIN")) (3)
authorize("/db/**", "hasRole('ADMIN') and hasRole('DBA')") (4)
authorize(anyRequest, denyAll) (5)
}
}
}
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. |