此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Security 6.4.1! |
架构
本节讨论 Spring Security 在基于 Servlet 的应用程序中的高级体系结构。 我们在参考的 Authentication, Authorization, Protection Against Exploits 部分建立了这种高层次的理解。
A 综述Filter
Spring Security 的 Servlet 支持基于 Servlet s,因此通常首先查看 s 的角色是有帮助的。
下图显示了单个 HTTP 请求的处理程序的典型分层。Filter
Filter
客户端向应用程序发送请求,容器创建一个包含 s 的请求,该请求应根据请求 URI 的路径进行处理。
在 Spring MVC 应用程序中,它是DispatcherServlet的
实例。
最多只能处理单个 和 。
但是,可以使用多个 API 来:FilterChain
Filter
Servlet
HttpServletRequest
Servlet
Servlet
HttpServletRequest
HttpServletResponse
Filter
-
防止下游 s 或 the 被调用。 在这种情况下,通常会写入 .
Filter
Servlet
Filter
HttpServletResponse
-
修改下游 s 和
HttpServletRequest
HttpServletResponse
Filter
Servlet
力量来自传递给它的东西。Filter
FilterChain
FilterChain
使用示例-
Java
-
Kotlin
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// do something before the rest of the application
chain.doFilter(request, response); // invoke the rest of the application
// do something after the rest of the application
}
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
// do something before the rest of the application
chain.doFilter(request, response) // invoke the rest of the application
// do something after the rest of the application
}
由于 a 仅影响下游 s 和 ,因此每个 的调用顺序非常重要。Filter
Filter
Servlet
Filter
委托过滤器代理
Spring 提供了一个名为 DelegatingFilterProxy
的实现,它允许在 Servlet 容器的生命周期和 Spring 的生命周期之间进行桥接。
Servlet 容器允许使用自己的标准注册 ,但它不知道 Spring 定义的 Bean。 可以通过标准的 Servlet 容器机制进行注册,但将所有工作委托给实现 .Filter
ApplicationContext
Filter
DelegatingFilterProxy
Filter
下面是如何适应 Filter
和 FilterChain
的图片。DelegatingFilterProxy
DelegatingFilterProxy
查找Bean 过滤器0从 和 然后调用ApplicationContext
Bean 过滤器0.
的伪代码可以在下面看到。DelegatingFilterProxy
DelegatingFilterProxy
伪代码-
Java
-
Kotlin
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// Lazily get Filter that was registered as a Spring Bean
// For the example in DelegatingFilterProxy delegate
is an instance of Bean Filter0
Filter delegate = getFilterBean(someBeanName);
// delegate work to the Spring Bean
delegate.doFilter(request, response);
}
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
// Lazily get Filter that was registered as a Spring Bean
// For the example in DelegatingFilterProxy delegate
is an instance of Bean Filter0
val delegate: Filter = getFilterBean(someBeanName)
// delegate work to the Spring Bean
delegate.doFilter(request, response)
}
另一个好处是它允许延迟查找 bean 实例。
这一点很重要,因为容器需要先注册实例,然后才能启动容器。
但是, Spring 通常使用 a 来加载 Spring Bean,直到需要注册实例后才会完成。DelegatingFilterProxy
Filter
Filter
ContextLoaderListener
Filter
FilterChainProxy
Spring Security 的 Servlet 支持包含在 中。 是 Spring Security 提供的特殊功能,它允许通过SecurityFilterChain
委托给许多实例。
由于 是一个 Bean,因此它通常包装在 DelegatingFilterProxy 中。FilterChainProxy
FilterChainProxy
Filter
Filter
FilterChainProxy
SecurityFilterChain 安全过滤器链
SecurityFilterChainProxy使用FilterChain
来确定应该为此请求调用哪些 Spring Security。Filter
中的安全过滤器通常是 Bean,但它们是用 DelegatingFilterProxy 而不是 DelegatingFilterProxy 注册的。 为直接向 Servlet 容器或 DelegatingFilterProxy 注册提供了许多优势。
首先,它为 Spring Security 的所有 Servlet 支持提供了一个起点。
因此,如果您尝试对 Spring Security 的 Servlet 支持进行故障排除,那么添加调试点是一个很好的起点。SecurityFilterChain
FilterChainProxy
FilterChainProxy
FilterChainProxy
其次,由于它是 Spring Security 使用的核心,因此它可以执行不被视为可选的任务。
例如,它会清除 以避免内存泄漏。
它还应用 Spring Security 的 HttpFirewall
来保护应用程序免受某些类型的攻击。FilterChainProxy
SecurityContext
此外,它还在确定何时应调用 a 方面提供了更大的灵活性。
在 Servlet 容器中,仅根据 URL 调用 s。
但是,可以通过利用该接口根据 中的任何内容来确定调用。SecurityFilterChain
Filter
FilterChainProxy
HttpServletRequest
RequestMatcher
其实,可以用来决定应该用哪个。
这允许为应用程序的不同切片提供完全独立的配置。FilterChainProxy
SecurityFilterChain
在多个 SecurityFilterChain 中,Figure 决定应该使用哪个。
只会调用第一个匹配的 ID。
如果请求 的 URL,它将首先匹配 的 模式,因此即使它也匹配 ,也只会调用。
如果请求的 URL ,它将与 的 模式不匹配,因此将继续尝试每个 。
假设没有其他实例匹配,则将被调用。FilterChainProxy
SecurityFilterChain
SecurityFilterChain
/api/messages/
SecurityFilterChain0
/api/**
SecurityFilterChain0
SecurityFilterChainn
/messages/
SecurityFilterChain0
/api/**
FilterChainProxy
SecurityFilterChain
SecurityFilterChain
SecurityFilterChainn
请注意,仅配置了三个 security s 实例。
但是,配置了四个安全 s。
请务必注意,每个 Cookie 都可以是唯一的,并且可以单独配置。
事实上,如果应用程序希望 Spring Security 忽略某些请求,则 a 可能具有零安全性。SecurityFilterChain0
Filter
SecurityFilterChainn
Filter
SecurityFilterChain
SecurityFilterChain
Filter
安全过滤器
安全筛选器使用 SecurityFilterChain API 插入到 FilterChainProxy 中。
Filter
的顺序很重要。
通常不需要知道 Spring Security 的 Sequences。
但是,有时了解顺序是有益的Filter
以下是 Spring Security 过滤器订购的完整列表:
-
ChannelProcessingFilter
-
WebAsyncManagerIntegrationFilter
-
SecurityContextPersistenceFilter
-
HeaderWriterFilter
-
CorsFilter 过滤器
-
Csrf过滤器
-
LogoutFilter
-
OAuth2AuthorizationRequestRedirectFilter
-
Saml2WebSsoAuthenticationRequestFilter
-
X509AuthenticationFilter
-
AbstractPreAuthenticatedProcessingFilter
-
CasAuthenticationFilter 的
-
OAuth2LoginAuthenticationFilter
-
Saml2WebSsoAuthenticationFilter
-
OpenIDAuthenticationFilter
-
DefaultLoginPageGeneratingFilter
-
DefaultLogoutPageGeneratingFilter
-
ConcurrentSessionFilter
-
BearerTokenAuthenticationFilter
-
RequestCacheAwareFilter
-
SecurityContextHolderAwareRequestFilter
-
JaasApiIntegrationFilter
-
RememberMeAuthenticationFilter
-
匿名身份验证过滤器
-
OAuth2AuthorizationCodeGrantFilter
-
会话管理过滤器
-
SwitchUserFilter
处理安全异常
ExceptionTranslationFilter
允许将 AccessDeniedException
和 AuthenticationException
转换为 HTTP 响应。
ExceptionTranslationFilter
作为安全筛选器之一插入到 FilterChainProxy 中。
-
首先,调用 以调用应用程序的其余部分。
ExceptionTranslationFilter
FilterChain.doFilter(request, response)
-
如果用户未经过身份验证或用户是 ,则开始身份验证。
AuthenticationException
-
保存在
RequestCache
中。 当用户成功进行身份验证时,将使用 重播原始请求。HttpServletRequest
RequestCache
-
用于从客户端请求凭据。 例如,它可能会重定向到登录页面或发送标头。
AuthenticationEntryPoint
WWW-Authenticate
-
否则,如果它是 ,则为 Access Denied。 调用 以处理被拒绝的访问。
AccessDeniedException
AccessDeniedHandler
如果应用程序不抛出 an 或 an ,则不执行任何操作。 |
的伪代码如下所示:ExceptionTranslationFilter
try {
filterChain.doFilter(request, response); (1)
} catch (AccessDeniedException | AuthenticationException ex) {
if (!authenticated || ex instanceof AuthenticationException) {
startAuthentication(); (2)
} else {
accessDenied(); (3)
}
}
1 | 您将从 A Review of Filter 中回想起,调用等效于调用应用程序的其余部分。
这意味着,如果应用程序的另一部分(即FilterSecurityInterceptor 或方法安全性)抛出OR,它将在此处被捕获并处理。FilterChain.doFilter(request, response) AuthenticationException AccessDeniedException |
2 | 如果用户未经过身份验证或用户是 ,则开始身份验证。AuthenticationException |
3 | 否则,Access Denied (访问被拒绝) |