Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring安全性:使用PersistentTokenBasedMemberMeservices的CookiethefteException_Java_Spring_Spring Boot_Spring Security - Fatal编程技术网

Java Spring安全性:使用PersistentTokenBasedMemberMeservices的CookiethefteException

Java Spring安全性:使用PersistentTokenBasedMemberMeservices的CookiethefteException,java,spring,spring-boot,spring-security,Java,Spring,Spring Boot,Spring Security,我有一个使用SpringBoot2.0.1的web应用程序,它受到SpringSecurity的保护。我使用PersistentTokenRepository来记住我,并将令牌存储在MySQL数据库中 在服务器日志文件中,我看到大量带有CookiethefteExceptions的堆栈跟踪。它太多了,我很难相信真的饼干被偷了,但却假设了某种错误的配置。通过添加一些分析代码,似乎只有移动浏览器受到影响 Servlet.service() for servlet [dispatcherServlet

我有一个使用SpringBoot2.0.1的web应用程序,它受到SpringSecurity的保护。我使用
PersistentTokenRepository
来记住我,并将令牌存储在MySQL数据库中

在服务器日志文件中,我看到大量带有
CookiethefteException
s的堆栈跟踪。它太多了,我很难相信真的饼干被偷了,但却假设了某种错误的配置。通过添加一些分析代码,似乎只有移动浏览器受到影响

Servlet.service() for servlet [dispatcherServlet] in context with path [/r] threw exception
  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.4.RELEASE.jar!/:5.0.4.RELEASE]
手动测试无法重现这一点。删除会话cookie,但保留“记住我”cookie并向受限URL发出请求将导致正常的已验证会话

以下是我的安全配置的相关部分:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
    @Configuration
    public static class SecurityConfiguration extends WebSecurityConfigurerAdapter {

        @Autowired
        private RememberMeServices rememberMeServices;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .rememberMe()
                    .key(rememberMeKey)
                    .rememberMeServices(rememberMeServices);
            ;
        }
    }

    /**
     * Key for RememberMeServices and RememberMeAuthenticationProvider.
     */
    private static final String rememberMeKey = "...";

    @Bean
    public RememberMeServices rememberMeServices(UserDetailsService userDetailsService, PersistentTokenRepository persistentTokenRepository) {
        PersistentTokenBasedRememberMeServices rememberMeServices = new AnalyzingPersistentTokenBasedRememberMeServices(
                rememberMeKey, userDetailsService, persistentTokenRepository);
        rememberMeServices.setTokenValiditySeconds((int) Duration.of(366L, ChronoUnit.DAYS).toSeconds());
        return rememberMeServices;
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository(JdbcTemplate jdbcTemplate) {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setJdbcTemplate(jdbcTemplate);
        return tokenRepository;
    }
}
analyzingPersistentTokenBasedMemberMeservices
是一个
PersistentTokenBasedMemberMeservices
,带有一些额外的登录
ProcessAutologyCookie

另一个特点是,我使用一个定制的
AuthenticationProvider
,并提供一个
UserDetailsService
仅用于记忆。但如上所述,手动测试工作正常。不过,用户报告他们注销的次数太多(会话超时为24小时)


有没有人经历过这样的事情并有解决办法?我是否错过了一些关键配置?

PersistentTokenBasedMemberMeservices
不适用于具有并发请求的应用程序,这些请求可能会发送相同的令牌系列

请参阅这些已存在近五年且尚未解决的错误报告:


使用
TokenBasedMemberMeservices
没有这些问题。

我最终使用Redisson实现分布式锁定和分布式映射来保存快速过期的缓存,允许一批并发请求中的第一个到达请求续订令牌,并允许后续请求知道令牌最近已刷新并使用该新值

在spring security web 4.2.13中令牌延长机制的实现问题

protected UserDetails processAutoLoginCookie(String[] cookieTokens,...
  .....
    PersistentRememberMeToken newToken = new PersistentRememberMeToken(
            token.getUsername(), token.getSeries(), generateTokenData(), new Date());

    try {
        tokenRepository.updateToken(newToken.getSeries(), newToken.getTokenValue(),
                newToken.getDate());
        addCookie(newToken, request, response);
    }
    catch (Exception e) {
        logger.error("Failed to update token: ", e);
        throw new RememberMeAuthenticationException(
                "Autologin failed due to data access problem");
    } 
在刷新期间,在并发请求的情况下,同一系列的令牌值可以在DB中重写几次,但在cookie中可以保存另一个值

登录期间的令牌创建工作正常,在最坏的情况下,数据库中可以有许多持久化令牌,但其中一个可以工作=)

在我的项目中,我通过修改刷新算法修复了错误:

   if (token.date + 1 < new Date()){
       try {
            PersistentRememberMeToken newToken = new PersistentRememberMeToken( token.getUsername(), generateSeriesData(), generateTokenData(), new Date())
            tokenRepository.createNewToken(newToken)
            addCookie(newToken, request, response)
        }
        catch (Exception e) {
            logger.error("Failed to update token: ", e);
            throw new RememberMeAuthenticationException(
                    "Autologin failed due to data access problem");
        }
    }  
if(token.date+1

此代码在结果时生成许多DB记录,但有效

此答案有点误导。在大多数情况下,人们选择PersistentTokenBasedMemberMeservices是因为TokenBasedMemberMeservices一开始就不适合。也就是说,它不那么安全。