我不知道如何最好地构建这个问题。请允许我解释一下这个问题。
在我的网络应用程序中,我有一个页面,我在其中使用基于AJAX的发布请求来从数据库中分页记录。可以对检索到的记录集进行更改,并通过基于AJAX的发布请求进行更新。由于每个请求中传递的敏感信息,这些请求属于post类型。
问题
如果用户登录时选中了“记住我”。在AJAX分页页面上,如果用户第一次单击下一个按钮以在会话超时后检索新的记录集,则它会成功运行。然后,如果用户再次单击下一个按钮以检索另一组记录,则会抛出InvalidCsrfTokenException
,导致我的自定义AccessDeniedHandler
将用户重定向到登录页面。我不希望用户被重定向到登录而不是请求应该成功,因为记住我的cookie仍然有效,尽管HTTP会话已经过期。
我注意到,当会话超时后发出第一个AJAX请求时,会为X-XSRF-TOKEN
分配一个新的令牌值。随后的ajax请求(第二个AJAX请求)然后抛出InvalidCsrfTokenException
,因为新的令牌值不再与未更新的页面上的先前CSRF值(即sec:csrfMetaTags
)匹配,因为请求是AJAX-基于
那么请问如何在AJAX请求中更新页面CSRF值(即sec:csrfMetaTags
)以匹配X-XSRF-TOKEN
值?有弹簧开箱即用的解决方案吗?如果不是,那么对这个问题的任何更好的方法都会非常感激。感谢。
答案 0 :(得分:0)
如果我理解你的问题,你可以使用Spring安全性Taglib将CSRF令牌放入元标记中。这会给您一个问题,因为这只在呈现页面时执行一次。
当会话超时时,特别是涉及安全性时,AJAX请求出现问题是很常见的。
我们通常通过确保会话不会消亡来解决这个问题。这个完成了 通过拥有前端开发人员可以调用的端点,刷新会话并告诉他何时到期。每次会话接近到期时,前端都会调用此端点。如果用户计算机进入待机状态,并且会话在关闭时会到期,则前端会在重新打开电源时知道这一点,并且会重新加载页面以便您获取新的CSRF令牌。如果您使用良好的生根框架或本地存储,则可以避免失去用户的状态。
我建议不要尝试构建任何变通方法以避免页面重新加载。我见过开发人员构建了一个返回当前CSRF令牌的端点,然后使用JavaScript更新元头以避免重新加载页面。这是一个非常糟糕的主意,因为黑客也可以使用端点来获取令牌。总是要小心安全性,即使大公司遭到黑客攻击也是有原因的,安全性并不像看起来那么简单。
答案 1 :(得分:0)
csrfMetaTags
将CSRF令牌包含在页面中。但是,在重新加载页面之前,CSRF令牌永远不会更新。
csrfMetaTags代码
如果启用了CSRF保护,则此标记会插入包含CSRF保护令牌表单字段和标题名称以及CSRF保护令牌值的元标记。这些元标记对于在应用程序中的JavaScript中使用CSRF保护非常有用。
您应该将
csrfMetaTags
放在HTML<head></head>
块中,您通常会放置其他元标记。使用此标记后,您可以使用JavaScript轻松访问表单字段名称,标题名称和标记值。
有一些解决方案,请参阅Spring Security Reference:
<强>超时强>
一个问题是预期的CSRF令牌存储在HttpSession中,因此只要HttpSession到期,您配置的
AccessDeniedHandler
就会收到InvalidCsrfTokenException。如果您使用默认的AccessDeniedHandler
,浏览器将获得HTTP 403并显示错误的错误消息。[...]
缓解活动用户遇到超时的一种简单方法是使用一些JavaScript让用户知道他们的会话即将过期。用户可以单击按钮继续并刷新会话。
或者,指定自定义
AccessDeniedHandler
可让您以任何方式处理InvalidCsrfTokenException
。有关如何自定义AccessDeniedHandler
的示例,请参阅为xml和Java配置提供的链接。最后,可以将应用程序配置为使用不会过期的
CookieCsrfTokenRepository
。如前所述,这不如使用会话安全,但在许多情况下可以很好。