对于最新的稳定版本,请使用 Spring Security 6.4.1! |
使用 FilterSecurityInterceptor 授权 HttpServletRequest
|
本节以 Servlet 体系结构和实现为基础,深入探讨了授权在基于 Servlet 的应用程序中的工作原理。
这FilterSecurityInterceptor
提供HttpServletRequest
实例。
它作为 Security Filters 之一插入到 FilterChainProxy 中。
下图显示了FilterSecurityInterceptor
:

这
FilterSecurityInterceptor
从SecurityContextHolder获取Authentication。
FilterSecurityInterceptor
创建一个FilterInvocation
从HttpServletRequest
,HttpServletResponse
和FilterChain
)传递到FilterSecurityInterceptor
.它将
FilterInvocation
自SecurityMetadataSource
要获取ConfigAttribute
s. 它传递
Authentication
,FilterInvocation
和ConfigAttribute
s 到AccessDecisionManager
.如果授权被拒绝,则
AccessDeniedException
被抛出。
在这种情况下,ExceptionTranslationFilter
处理AccessDeniedException
.如果授予访问权限,
FilterSecurityInterceptor
继续FilterChain
,这样应用程序就可以正常处理了。
默认情况下,Spring Security 的授权要求对所有请求进行身份验证。 下面的清单显示了显式配置:
我们可以通过按优先级顺序添加更多规则来将 Spring Security 配置为具有不同的规则:
-
Java
-
XML
-
Kotlin
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.authorizeRequests(authorize -> authorize (1)
.requestMatchers("/resources/**", "/signup", "/about").permitAll() (2)
.requestMatchers("/admin/**").hasRole("ADMIN") (3)
.requestMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')") (4)
.anyRequest().denyAll() (5)
);
return http.build();
}
<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>
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
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)
}
}
return http.build()
}
1 | 指定了多个授权规则。 每个规则都按照其声明的顺序进行考虑。 |
2 | 我们指定了任何用户都可以访问的多个 URL 模式。 具体而言,如果 URL 以“/resources/”开头、等于“/signup”或等于“/about”,则任何用户都可以访问请求。 |
3 | 任何以 “/admin/” 开头的 URL 都将被限制为具有 “ROLE_ADMIN” 角色的用户。
您会注意到,由于我们正在调用hasRole 方法,则不需要指定 “ROLE_” 前缀。 |
4 | 任何以 “/db/” 开头的 URL 都要求用户同时具有 “ROLE_ADMIN” 和 “ROLE_DBA”。
您会注意到,由于我们使用的是hasRole 表达式,则不需要指定 “ROLE_” 前缀。 |
5 | 任何尚未匹配的 URL 都将被拒绝访问。 如果您不想意外忘记更新授权规则,这是一个很好的策略。 |
使用 Dispatcher 类型配置 FilterSecurityInterceptor
默认情况下,FilterSecurityInterceptor
适用于每个请求。
这意味着,如果请求是从已过滤的请求中分派的,则FilterSecurityInterceptor
将对 dispatched 请求执行相同的授权检查。
在某些情况下,您可能不希望对某些 Dispatcher 类型应用授权:
-
Java
-
XML
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
http
.authorizeRequests((authorize) -> authorize
.dispatcherTypeMatchers(DispatcherType.ASYNC, DispatcherType.ERROR).permitAll()
.anyRequest.authenticated()
)
// ...
return http.build();
}
<http auto-config="true">
<intercept-url request-matcher-ref="dispatcherTypeMatcher" access="permitAll" />
<intercept-url pattern="/**" access="authenticated"/>
</http>
<b:bean id="dispatcherTypeMatcher" class="org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher">
<b:constructor-arg value="ASYNC"/>
<b:constructor-arg value="ERROR"/>
</b:bean>