Spring 安全记住我失败并出现 CookieTheftException

Spring Security Remember Me fails with CookieTheftException

我的 SecurityConfig class 我在其中配置由 userServicepersistenceTokenRepository() 支持的记住我功能:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .antMatchers(
                    "/js/**",
                    "/css/**",
                    "/img/**",
                    "/webjars/**").permitAll()
            .anyRequest().authenticated()
    // ... and login, and logout
    .and()
        .rememberMe()
            .userDetailsService(userService)
            .tokenRepository(persistentTokenRepository());
}

@Bean
public PersistentTokenRepository persistentTokenRepository() {
    JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
    tokenRepository.setDataSource(dataSource);
    return tokenRepository;
}

用例:

  1. 用户在他的浏览器中打开登录页面,使用启用的 "Remember Me" 选项授权自己。
  2. [后端] 新的 remember-me 令牌已生成,保存在数据库中并发送给用户。默认有效期为 2 周。
  3. 用户被重定向到主页。
  4. 用户关闭浏览器以结束浏览会话。
  5. 用户再次启动浏览器并再次进入主页。

预期结果: [后端]无异常,DB中的token与remember-me cookie匹配。 [前端]用户认证成功,可以进入首页
实际结果:抛出[后端]CookieTheftException。令牌已从数据库中删除。 [前端] 用户被重定向到登录页面。

org.springframework.security.web.authentication.rememberme.CookieTheftException: Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack.
    at org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices.processAutoLoginCookie(PersistentTokenBasedRememberMeServices.java:119) ~[spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]

这里已经回答了这个问题:Spring Security Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack。 “记住我”功能在该答案中有详细说明,我建议您在应用以下解决方案之前先阅读它。

我想分享我的 Java 配置解决方案。从 webapp 页面安全性中分离静态资源安全性:

http
    .authorizeRequests()
    .antMatchers(
        "/js/**",
        "/css/**",
        "/img/**",
        "/webjars/**").permitAll();

http
    .authorizeRequests()
    .anyRequest().authenticated()
    // ... and login, and logout
    .and()
    .rememberMe()
    .userDetailsService(userService)
    .tokenRepository(persistentTokenRepository());

这两个配置是否单独定义取决于你 configure(HttpSecurity http) 方法或将它们分成两个 @Configuration 类。如果选择后一个选项,请不要忘记在这些配置上添加 @Order(int) 注释,否则会发生冲突。