Spring Security Invalid remember-me token (Series/token) 不匹配。暗示先前的 cookie 盗窃攻击

标签 spring spring-security tomcat7 remember-me

我有一个使用 Spring Security3.1.2 在 tomcat 7 中运行的 GWT 应用程序。我正在使用 UsernamePasswordAuthenticationFilter 和 PersistentTokenBasedRememberMeServices 在数据库上持久登录。此外,我也在使用 tomcat PersistentManager 将 session 保存在数据库中。 现在我的问题是,每次我尝试登录时,我都会得到 Invalid remember-me token (Series/token) mismatch CookieTheftException(我在下面添加了堆栈)。 我尝试从 tomcat_sessions 表中删除 session ,如下所示

  1. 关闭tomcat
  2. 从 tomcat_sessions 表中删除记录
  3. 启动tomcat
  4. 尝试登录我再次收到 CookieTheftException 的应用程序...

我还注意到,即使删除了 tomcat_sessions 表中的所有记录,当我重新启动 tomcat 时,tomcat_sessions 也会被我之前删除的所有 session 填满......

我还删除了 Spring persistent_logins 表中的所有记录并禁用了 tomcat PersistentManager 但仍然遇到同样的问题...

知道可能是什么问题吗?谢谢

SEVERE: Servlet.service() for servlet [springMvcServlet] in context with path [/brate] 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:102)
    at org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices.autoLogin(AbstractRememberMeServices.java:115)
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:97)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at com.brate.admin.server.servlet.crawler.GoogleBotFilter.doFilter(GoogleBotFilter.java:202)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:695)

最佳答案

为了让我们在同一个页面上,我将先花一点时间解释我如何理解这种持久 token 机制的工作原理。

从头开始(persistent_logins 表中没有条目):

登录成功: 将使用一些随机散列为用户创建一个持久 token 。 为用户创建了一个带有 token 详细信息的 cookie。 为用户创建一个 session 。

只要用户仍然有一个事件 session ,就不会在身份验证时调用记住我功能。

用户 session 过期后: 记住我功能启动并使用 cookie 从数据库中获取持久 token 。如果持久化 token 与来自 cookie 的 token 匹配,那么每个人都会在用户通过身份验证时感到高兴,生成一个新的随机散列,并用它更新持久化 token ,并且用户的 cookie 也会针对后续请求进行更新。

但如果 cookie 中的 token 与持久 token 的 token 不匹配,那么您会收到 CookieTheftException。 token 不匹配的最常见原因是 2 个或更多请求被快速连续触发,第一个请求将通过,为后续请求生成新哈希,但第二个请求仍将使用旧 token 它并因此导致异常。

为了在很大程度上避免 CookieTheftException,请确保对 webapp 内容(例如图像、字体、脚本等)的请求不通过 Springs 身份验证过滤器。为此,只需添加另一个 <http>配置高于您的正常安全配置并指定您不希望对资源的请求有任何安全性(使用您的相关路径而不是 /resources/** ):

<http pattern="/resources/**" security="none"/>
<http ... (normal config) ... 

(Java 配置见这里:How do I define http "security = 'none' in JavaConfig?)

如果您从数据库中删除用户的 token (并且他们的 session 已过期),则该用户将在下一次请求时注销。所以你所说的关于你的持久 token (在 persistent_logins 表中)自动重新创建的意义不大,我非常怀疑情况是否如此。 PersistentTokenRepositorycreateNewToken(PersistentRememberMeToken token)方法仅在登录成功时调用。

最后,如果您仍然遇到异常,请附上 PersistentTokenBasedRememberMeServices 的源代码。并在 processAutoLoginCookie 中设置一个断点方法来查看哪个请求导致了 CookieTheftException。

我希望这会有所帮助。

关于Spring Security Invalid remember-me token (Series/token) 不匹配。暗示先前的 cookie 盗窃攻击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20053107/

相关文章:

java - 升级到 Thymeleaf 3 并在 Spring 中重新实现富 HTML 电子邮件

java - 如何基于用户代理等在 Spring MVC 中从数据库加载主题

java - 授权码流程和多个选项卡

java - Spring Security、尾部斜杠和 URL 中的点

java - 外部资源(JS)在 spring mvc app 中的位置

Spring Boot MVC,没有返回我的观点

java - 使用 Spring 框架以原子方式维护服务层事务和数据库日志记录

spring-security - Spring OAuth : Resource Server with Authorization Server backend

java - CXF JAVA 消息截断

java - 如何更改 apache tomcat acess url 的名称?