解锁 Spring Security:深入底层原理
Spring Security 是一个强大且灵活的安全框架,其核心功能包括身份认证、授权和防御常见攻击。要深入了解其底层原理,需要理解以下关键概念和组件。而Spring Security的底层原理是传统的 Servlet过滤器 ,欲了解更多详细信息,您可以访问 Architecture :: Spring Security。
1. A Review of Filters
下图展示了处理一个Http请求时,过滤器和Servlet的工作流程
客户端向应用程序发送请求,容器根据请求 URI 的路径创建一个FilterChain ,其中包含应处理HttpServletRequest的Filter实例和Servlet 。在 Spring MVC 应用程序中,Servlet是DispatcherServlet的实例。一个Servlet最多可以处理一个HttpServletRequest和HttpServletResponse 。然而,多个Filter可用于:
- 防止调用下游
Filter实例或Servlet。在这种情况下,Filter通常会写入HttpServletResponse。 - 修改下游
Filter实例和Servlet使用的HttpServletRequest或HttpServletResponse。
FilterChain的使用示例:
1 | public void doFilter(ServletRequest request, |
由于Filter仅影响下游Filter实例和Servlet ,因此调用每个Filter顺序非常重要。
2. DelegatingFilterProxy
Spring 提供了一个名为DelegatingFilterProxy的Filter实现,它允许在 Servlet 容器的生命周期和 Spring 的ApplicationContext之间进行桥接。 Servlet容器允许使用自己的标准注册Filter实例,但它不知道Spring定义的Bean。可以通过标准 Servlet 容器机制注册DelegatingFilterProxy ,但将所有工作委托给实现Filter Spring Bean。
DelegatingFilterProxy从ApplicationContext中查找 Bean Filter 0 ,然后调用 Bean Filter 0。
1 | public void doFilter(ServletRequest request, |
DelegatingFilterProxy的另一个好处是它允许延迟查找Filter bean 实例。这很重要,因为容器需要在容器启动之前注册Filter实例。然而,Spring 通常使用ContextLoaderListener来加载 Spring Bean,直到需要注册Filter实例之后才会完成此操作。
3. FilterChainProxy
Spring Security 的 Servlet 支持包含在FilterChainProxy中。 FilterChainProxy是 Spring Security 提供的一个特殊Filter ,它允许通过 SecurityFilterChain 委托给许多Filter实例。由于FilterChainProxy是一个 Bean,因此它通常包装在 DelegatingFilterProxy 中。
4. SecurityFilterChain
FilterChainProxy使用SecurityFilterChain来确定应为当前请求调用哪些 Spring Security Filter实例。
SecurityFilterChain中的安全过滤器通常是 Bean,但它们是使用FilterChainProxy而不是DelegatingFilterProxy注册的。 FilterChainProxy提供了直接向 Servlet 容器或DelegatingFilterProxy注册的许多优点。首先,它为 Spring Security 的所有 Servlet 支持提供了一个起点。因此,如果尝试对 Spring Security 的 Servlet 支持进行故障排除,那么在FilterChainProxy中添加调试点是一个很好的起点。
由于FilterChainProxy是 Spring Security 使用的核心,因此它可以执行不被视为可选的任务。例如,它清除SecurityContext以避免内存泄漏。它还应用 Spring Security 的HttpFirewall来保护应用程序免受某些类型的攻击。
它在确定何时应调用SecurityFilterChain方面提供了更大的灵活性。在 Servlet 容器中,仅根据 URL 调用Filter实例。但是, FilterChainProxy可以使用RequestMatcher接口根据HttpServletRequest中的任何内容确定调用。
在上图中, FilterChainProxy决定应使用哪个SecurityFilterChain 。仅调用第一个匹配的SecurityFilterChain 。如果请求/api/messages/的 URL,它首先匹配/api/**的SecurityFilterChain 0模式,因此仅调用SecurityFilterChain 0 ,即使它也匹配SecurityFilterChain n 。如果请求/messages/的 URL,则它与/api/**的SecurityFilterChain 0模式不匹配,因此FilterChainProxy继续尝试每个SecurityFilterChain 。假设没有其他SecurityFilterChain实例匹配,则调用SecurityFilterChain n 。SecurityFilterChain 0仅配置了三个安全Filter实例。然而, SecurityFilterChain n配置了四个安全Filter实例。需要注意的是,每个SecurityFilterChain都可以是唯一的,并且可以单独配置。事实上,如果应用程序希望 Spring Security 忽略某些请求, SecurityFilterChain安全Filter实例可能为零。
5. Security Filters
安全过滤器通过SecurityFilterChain API 插入到FilterChainProxy中。这些过滤器可用于多种不同的目的,例如身份验证、授权、漏洞保护等。过滤器按照特定的顺序执行,以保证它们在正确的时间被调用,例如,执行身份验证的Filter应该在执行授权的Filter之前被调用。通常不需要知道 Spring Security 的Filter的顺序。但是,有时了解顺序是有好处的,如果您想了解它们,可以检查FilterOrderRegistration代码。
1 |
|
