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

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

问题描述

我有一个在tomcat 7中运行的使用Spring Security3.1.2的GWT应用程序.我正在使用UsernamePasswordAuthenticationFilter和PersistentTokenBasedRememberMeServices在DB上保留登录名.此外,我也使用tomcat PersistentManager将会话保存到DB中. 现在我的问题是,每次尝试登录时,我都会得到无效的记住我"令牌(系列/令牌)与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. 关闭雄猫
  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...

我还删除了Springpersistent_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.令牌不匹配的最常见原因是快速连续触发了两个或更多请求,第一个请求将通过,并为随后的请求生成新的哈希,但第二个请求仍将旧令牌打开它并因此导致异常.

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身份验证过滤器.为此,只需在常规安全配置之上添加另一个<http>配置,并指定对资源请求不希望有任何安全性(使用相关路径而不是/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 Config,请参见此处:如何定义http" security ='none'in 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天全站免登陆