跳至主要內容

RememberMeAuthenticationFilter

Jin大约 5 分钟

RememberMeAuthenticationFilter

RememberMeAuthenticationFilter 是用于处理 "记住我" 功能的过滤器。这个功能允许用户在成功登录后,即使关闭浏览器或在一定时间内没有活动,依然保持登录状态,从而避免频繁要求用户重新输入用户名和密码。

RememberMeAuthenticationFilter 主要负责从请求中提取 "记住我" 相关的认证信息(通常是一个由浏览器发送的 remember-me cookie),并基于这个信息恢复用户的身份认证信息。

1、功能简介

记住我功能允许用户在登录后选择是否在浏览器中保留登录状态。通常,这通过一个 remember-me cookie 来实现。当用户再次访问网站时,如果浏览器中存在有效的 remember-me cookie,Spring Security 会自动恢复用户的登录状态,而无需再次进行身份验证。

  • 用户在登录时选择 “记住我” 选项。
  • 系统将会生成一个持久的 remember-me cookie,通常包含加密的信息,用于标识用户。
  • 当用户关闭浏览器并重新打开时,如果 remember-me cookie 依然有效,Spring Security 会通过 RememberMeAuthenticationFilter 来恢复用户的认证状态。

2、RememberMeAuthenticationFilter 的工作流程

RememberMeAuthenticationFilter 主要有以下几个步骤:

  1. 请求到达:当用户请求一个受保护资源时,RememberMeAuthenticationFilter 会检查请求中是否存在 remember-me cookie(通常是名为 remember-me 或自定义名称的 cookie)。
  2. 验证 remember-me cookie:如果请求中存在 remember-me cookie,RememberMeAuthenticationFilter 会提取该 cookie 并验证其内容。验证的过程通常包括:
    • 解码并验证 cookie 中的加密信息。
    • 检查 cookie 是否有效(例如,检查过期时间、签名是否匹配等)。
  3. 恢复认证信息:如果 remember-me cookie 有效,RememberMeAuthenticationFilter 会将从 cookie 中提取的认证信息(通常是用户的 ID 和一些验证信息)转换成一个 Authentication 对象,并将其存储到 SecurityContextHolder 中。
  4. 继续处理请求:一旦用户的身份信息被恢复并存储在 SecurityContextHolder 中,Spring Security 将继续执行剩余的过滤器和请求处理流程,用户就能够访问受保护的资源。
  5. 认证失败:如果 remember-me cookie 无效或无效,过滤器会允许请求继续,且不会干预后续的认证流程。用户会被重定向到登录页面或者其他错误页面,取决于配置。

3、如何启用和配置 Remember Me 功能

在 Spring Security 中,启用和配置 “记住我” 功能通常涉及以下几个步骤:

  1. 启用 RememberMeAuthenticationFilter
    • 默认情况下,Spring Security 不会启用 RememberMeAuthenticationFilter,你需要通过 HttpSecurity 配置来启用这个功能。
  2. 配置 RememberMeAuthenticationFilter
    • 你需要配置一个 RememberMeServices,它会处理 cookie 的生成和验证。

3.1、配置示例

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated() // 配置所有请求都需要认证
            .and()
            .formLogin() // 启用表单登录
                .permitAll()
            .and()
            .rememberMe()  // 启用 "记住我" 功能
                .key("uniqueAndSecret")  // 用于签名 cookie 的密钥,确保安全性
                .tokenValiditySeconds(86400)  // cookie 有效期,单位为秒,这里是 24 小时
            .and()
            .httpBasic().disable();  // 禁用 HTTP Basic 认证
        return http.build();
    }
}

3.2、配置详解

  • rememberMe():启用 "记住我" 功能。
    • key():设置一个用于签名 cookie 的唯一密钥,这个密钥可以防止 cookie 被伪造。
    • tokenValiditySeconds():设置 remember-me cookie 的有效期,单位为秒。默认为 14 天(1209600 秒)。例如,86400 是一天的有效期。
  • SecurityFilterChain 定义了 Spring Security 的过滤器链。在这个例子中,rememberMe() 的配置将会启用 RememberMeAuthenticationFilter,该过滤器会自动拦截包含有效 remember-me cookie 的请求。

4、自定义 RememberMeServices

Spring Security 提供了 RememberMeServices 接口,它用于管理 remember-me cookie 的生成和验证。默认情况下,Spring Security 提供了一个基于 InMemoryRememberMeServices 的实现,它会将 remember-me 信息存储在内存中。

如果你希望使用数据库或其他存储机制来持久化用户的 remember-me 信息,你可以自定义 RememberMeServices

例如,可以自定义一个 JdbcTokenRepositoryImpl

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
            .and()
            .formLogin().permitAll()
            .and()
            .rememberMe()
                .tokenRepository(persistentTokenRepository()) // 自定义 token 存储库
                .tokenValiditySeconds(86400)
            .and()
            .httpBasic().disable();
        return http.build();
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource());  // 配置数据源
        return tokenRepository;
    }

    @Bean
    public DataSource dataSource() {
        // 配置数据源
        return new HikariDataSource();  // 假设使用 HikariCP 数据源
    }
}

在这个例子中,JdbcTokenRepositoryImpl 被用来将 remember-me token 存储在数据库中。这对于需要跨会话持久化的应用程序非常有用。

5、RememberMeAuthenticationFilter 的执行顺序

RememberMeAuthenticationFilter 在 Spring Security 过滤器链中的位置通常较为靠前,通常位于 UsernamePasswordAuthenticationFilter 之前。这意味着在用户名密码认证之前,Spring Security 会先检查是否存在有效的 remember-me cookie,如果存在并且有效,它将恢复用户的身份认证信息。

过滤器链顺序如下:

  1. SecurityContextPersistenceFilter:保证安全上下文的存在。
  2. RememberMeAuthenticationFilter:处理 "记住我" 功能。
  3. UsernamePasswordAuthenticationFilter:处理标准表单登录认证。
  4. 其他过滤器(如 ExceptionTranslationFilterFilterSecurityInterceptor 等)负责处理授权等任务。

6、总结

  • RememberMeAuthenticationFilter 是 Spring Security 中用于实现 “记住我” 功能的核心过滤器。它通过从浏览器请求中提取 remember-me cookie,恢复用户的认证状态,避免用户频繁登录。
  • 你可以通过 Spring Security 配置启用和定制 "记住我" 功能,支持自定义 cookie 的有效期、签名密钥以及持久化存储方案。
  • RememberMeAuthenticationFilter 通常与 UsernamePasswordAuthenticationFilter 配合工作,确保用户的认证信息在浏览器关闭后也能够保持有效。

通过 RememberMeAuthenticationFilter,Spring Security 提供了一个简便而安全的方式来实现长时间的用户登录保持,提升用户体验。

贡献者: Jin