跳至主要內容

SecurityContextPersistenceFilter

Jin大约 4 分钟

SecurityContextPersistenceFilter

SecurityContextPersistenceFilterSpring Security 中的一个过滤器,主要负责持久化和恢复与当前请求相关的安全上下文(SecurityContext)。

1、SecurityContext 是什么?

SecurityContext 是 Spring Security 用来保存当前用户安全信息的容器,通常包含以下内容:

  • Authentication:代表当前用户的认证信息,如用户名、角色、权限等。
  • Authorities:用户拥有的权限或角色。
  • SecurityContextHolder:用于存储当前线程的 SecurityContext

Spring Security 将安全上下文与当前请求生命周期关联,因此每个请求处理期间,Spring Security 会将该请求的安全上下文保持在 SecurityContextHolder 中,并且在请求结束后,将其清除。

2、SecurityContextPersistenceFilter 的作用

SecurityContextPersistenceFilter 主要有两个功能:

  1. 恢复 SecurityContext:每次请求到达时,SecurityContextPersistenceFilter 会从 HttpSession 中恢复先前保存的 SecurityContext。这样做是为了确保每个请求都可以访问到正确的认证信息。
  2. 清除 SecurityContext:在请求处理结束时,SecurityContextPersistenceFilter 会从 SecurityContextHolder 清除 SecurityContext,防止信息泄露给后续的请求。

3、SecurityContextPersistenceFilter 的工作原理

SecurityContextPersistenceFilter 的工作流程可以简要描述为以下几个步骤:

请求开始时:

  • SecurityContextPersistenceFilter 负责检查 HttpSession 是否存在有效的 SecurityContext ,如果存在,它会将该 SecurityContext 恢复到当前线程中的 SecurityContextHolder

请求处理时:

  • 当前请求的 SecurityContext 会被存储在 SecurityContextHolder 中,通常包含当前用户的认证信息。其他 Spring Security 组件(如 AuthenticationManagerUsernamePasswordAuthenticationFilter)可能会使用这些信息来处理安全性相关的操作。

请求结束时:

  • 在请求处理结束时,SecurityContextPersistenceFilter 会确保清除 SecurityContextHolder 中的 SecurityContext,防止线程池或后续请求中泄漏安全上下文。

4、配置和使用

SecurityContextPersistenceFilter 默认是由 Spring Security 自动配置和管理的,通常我们不需要显式地去配置它。这个过滤器会自动添加到 Spring Security 的过滤器链中,并且它会作为过滤器链中的第一个过滤器之一,以确保在其他过滤器之前进行安全上下文的恢复。

典型的配置

SecurityContextPersistenceFilter 是由 Spring Security 自动配置的,通常不会需要显式的配置。不过,如果需要定制,可以通过以下方式来进行调整:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .addFilterBefore(new MyCustomFilter(), SecurityContextPersistenceFilter.class)
        .authorizeRequests()
            .anyRequest().authenticated();
    return http.build();
}

5、与 SecurityContextHolderHttpSession 的关系

  • SecurityContextHolderSecurityContextHolder 是 Spring Security 的核心类之一,它用于持有当前线程的 SecurityContextSecurityContextPersistenceFilter 会在每次请求时,将 SecurityContext 设置到 SecurityContextHolder 中,处理完请求后再清除。
  • HttpSessionSecurityContext 通常会保存在 HttpSession 中,这样用户在多个请求之间保持认证信息。如果使用 Stateless 模式(例如 JWT ),SecurityContextPersistenceFilter 就不会从 HttpSession 中恢复信息,而是通过其他方式(如请求头)来维持用户身份。

6、SecurityContextPersistenceFilter 的工作流程

  1. 恢复 SecurityContext
    • 通过 SecurityContextRepository (默认是 HttpSessionSecurityContextRepository)从 HttpSession 中加载存储的 SecurityContext
    • SecurityContextPersistenceFilter 会把恢复的 SecurityContext 放入 SecurityContextHolder 中。
  2. 清除 SecurityContext
    • 请求结束后,SecurityContextPersistenceFilter 会清除当前线程中的 SecurityContextHolder 中的 SecurityContext

7、相关类和接口

  • SecurityContextRepository:这是一个接口,负责存储和加载 SecurityContext。默认实现是 HttpSessionSecurityContextRepository,它将 SecurityContext 存储在 HttpSession 中。
  • HttpSessionSecurityContextRepository:这是默认的 SecurityContextRepository 实现,它会将 SecurityContext 存储在 HttpSession 中。这是最常见的存储方式,适用于基于会话的认证机制。
  • Stateless Authentication:如果你的应用是无状态的(如使用 JWT 或其他 token 机制),你可以自定义 SecurityContextRepository,并配置 Spring Security 不使用 HttpSession 存储 SecurityContext

8、常见问题和注意事项

  • 会话过期/丢失:如果用户的 HttpSession 过期或者被清除,SecurityContextPersistenceFilter 将无法从会话中恢复 SecurityContext。在这种情况下,通常会导致用户被强制注销或需要重新认证。
  • 多线程环境:由于 SecurityContext 是绑定到当前线程的,SecurityContextPersistenceFilter 在每个请求中会为当前线程恢复或清除安全上下文。在线程池中使用时需要小心,因为 SecurityContext 可能被错误地共享到其他线程中。
  • Stateless 应用:在无状态(stateless)应用中,通常不使用 HttpSession 来存储 SecurityContext。此时,你可能会使用基于请求头(如 Bearer Token)的认证方式,而不依赖会话存储。
贡献者: Jin