Spring Security记住我因CookieTheftException

时间:2018-10-23 18:17:31

标签: spring spring-boot spring-security remember-me

我的SecurityConfig类,在其中配置由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. 用户在浏览器中打开“登录”页面,使用启用的“记住我”选项授权自己。
  2. [后端]生成新的“我记住”令牌,并将其保存在数据库中并发送给用户。默认有效期为2周。
  3. 用户被重定向到首页。
  4. 用户关闭浏览器以结束浏览会话。
  5. 用户再次启动浏览器并再次进入主页。

预期结果:[后端]毫无例外,数据库中的令牌与“记住我” 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]

1 个答案:

答案 0 :(得分:0)

此问题已在此处得到解答: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)批注,否则会发生冲突。