Spring Security 无效的记住我令牌(系列/令牌)不匹配.暗示先前的 cookie 盗窃攻击 [英] Spring Security Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack

查看:47
本文介绍了Spring Security 无效的记住我令牌(系列/令牌)不匹配.暗示先前的 cookie 盗窃攻击的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

i have a GWT application using Spring Security3.1.2 running in a tomcat 7. i am using UsernamePasswordAuthenticationFilter and PersistentTokenBasedRememberMeServices to persists logins on the DB. moreover, i am using tomcat PersistentManager to save session in DB as well. now my problem is that every time i try to login i get Invalid remember-me token (Series/token) mismatch CookieTheftException (i added the stack below). i tried deleting the session from tomcat_sessions table as follows

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

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

i also noticed that even after deleting all records in tomcat_sessions table and when i restart tomcat, tomcat_sessions gets filled up with all the session i deleted earlier...

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

i also deleted all records in Spring persistent_logins table and disabled tomcat PersistentManager but still having the same problem...

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

any idea what might be the problem? thank you

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)

推荐答案

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

Just so that we are on the same page I will first take a minute to explain how I understand this persistent token mechanism to work.

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

Starting from scratch (no entries in the persistent_logins table):

登录成功:将为用户创建一个具有一些随机散列的持久令牌.为用户创建了一个带有令牌详细信息的 cookie.为用户创建会话.

On login success: A persistent token will be created for the user with some random hash. A cookie is created for the user with the token details on it. A session is created for the user.

只要用户仍有活动会话,则在身份验证时不会调用记住我的功能.

As long as the user still has an active session then no remember me functionality will be invoked upon authentication.

用户会话过期后:记住我功能启动并使用 cookie 从数据库中获取持久令牌.如果持久令牌与 cookie 中的令牌匹配,那么当用户通过身份验证时,每个人都很高兴,生成一个新的随机哈希,并使用它更新持久令牌,并且用户的 cookie 也会为后续请求更新.

After the user's session has expired: The remember me functionality kicks in and uses the cookie to fetch the persistent token from the database. If the persisted token matches the one from the cookie then everyone is happy as the user gets authenticated, a new random hash is generated and the persistent token is updated with it and the user's cookie is updated as well for subsequent requests.

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

But if the token from the cookie doesn't match that of the persisted token then you get a CookieTheftException. The most common reason for the tokens not to match is that 2 or more request were fired off in quick succession, where the first request will get through, generating the new hash for following requests, but the second request will still have the old token on it and thus results in the exception.

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

To largely avoid the CookieTheftException, make sure that requests to your webapp's content (such as images, fonts, scripts etc.) don't go through Springs authentication filters. To do this simply add another <http> config above your normal security configuration and specify that you don't want any security for requests to you resources (use your relevant path instead of /resources/**):

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

(对于 Java 配置,请参见此处:我如何定义http "security = 'none' 在 JavaConfig 中?)

(For Java Config see here: How do I define http "security = 'none' in JavaConfig?)

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

If you delete an user's token from the database (and their session has expired), then the user will get logged out upon the next request. So what you are saying about your persistent tokens (in the persistent_logins table) automatically getting recreated makes very little sense and I highly doubt that is the case. The PersistentTokenRepository's createNewToken(PersistentRememberMeToken token) method only get's called on login success.

最后,如果您仍然遇到异常,那么附加 PersistentTokenBasedRememberMeServices 的源并在 processAutoLoginCookie 方法中放置一个断点以查看哪个请求是有帮助的导致 CookieTheftException.

Lastly if you're still getting the exception it helps to attach the sources for the PersistentTokenBasedRememberMeServices and to put a break point in the processAutoLoginCookie method to see which request is causing the CookieTheftException.

我希望这会有所帮助.

这篇关于Spring Security 无效的记住我令牌(系列/令牌)不匹配.暗示先前的 cookie 盗窃攻击的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆