在 Spring Security 中使用 CSRF 令牌获取 403

Posted

技术标签:

【中文标题】在 Spring Security 中使用 CSRF 令牌获取 403【英文标题】:Getting 403 with CSRF token in spring security 【发布时间】:2014-04-26 08:40:54 【问题描述】:

我遇到了多个选项卡的问题。如果我从第一个选项卡注销并打开另一个选项卡,登录并注销后,如果我返回第一个选项卡并登录,我会得到 403。例如,第一个选项卡的注销页面已由 spring security 和 thymeleaf 添加到表单中:

<input type="hidden" name="_csrf" value="7b9639ba-aaae-4ed2-aad2-bb4c5930458e">

作为第二个选项卡的登录表单添加了不同的 csrf 令牌。

<input type="hidden" name="_csrf" value="659324d5-ec5c-4c57-9984-dab740746285">

现在,当我转到第一个选项卡并从那里登录时,我得到 403 禁止。这是有道理的,因为 csrf 令牌现在已经过时了。但我该如何解决这个问题?如果用户从不活动状态中注销并重定向到登录页面但仅在一段时间后(例如半小时)再次尝试登录,我也会收到 403 禁止。

【问题讨论】:

你检查过 spring.io/blog/2013/08/21/… 的 spring 文档。登录问题似乎没有解决方法。关于你的最后一句话,这似乎是由于会话到期。 (文档中的超时部分) 我们遇到了类似的问题并使用自定义AccessDeniedHandler 解决了它(请参阅***.com/a/47399348/225217)。 【参考方案1】:

从 Spring Security 3.2 开始,我们有 CsrfTokenRepository 接口,它允许您存储同步器令牌,但您认为合适,例如在数据库中。这使您可以选择使这些令牌过期,以避免在您的用例中出现过时的令牌。

如果您想在出现问题时提供更好的错误消息,您可以提供一个自定义的AccessDeniedHandler 实现来管理MissingCsrfTokenExceptionInvalidCsrfTokenException 异常,以便生成一个更多信息。

更新:

我有一个拦截器来处理我所有未捕获的异常,所以我只是构建了一个小的 AccessDeniedHandler 来重新抛出与 CSRF 相关的异常:

public class CustomAccessDeniedHandler extends AccessDeniedHandlerImpl 
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException 
        if(accessDeniedException instanceof MissingCsrfTokenException
                || accessDeniedException instanceof InvalidCsrfTokenException) 
            throw new ServletException(accessDeniedException);
        
        super.handle(request, response, accessDeniedException);
    

【讨论】:

你在哪里注册这个处理程序类?你能举个例子吗?谢谢。 自从我使用 Spring 和 Spring Security 以来已经有很长时间了,此后我开始转向其他事情。不过,我会看看是否可以为您挖掘一些旧代码。 没关系,它在安全配置 HTTP.authenticationEntryPoint 中【参考方案2】:

我使用过的处理拒绝访问错误的最简单方法是在您的安全配置中设置拒绝访问处理程序以重定向到您的登录页面。

<http ...>
    <access-denied-handler error-page="/login.html" />
...

【讨论】:

以上是关于在 Spring Security 中使用 CSRF 令牌获取 403的主要内容,如果未能解决你的问题,请参考以下文章

在使用 Oauth、SAML 和 spring-security 的多租户的情况下从 spring-security.xml 中获取错误

无法获得 go daddy ssl 证书以使用 spring boot

在项目中使用Spring Security进行权限控制

在 grails 中使用 spring-security 插件时出错

使用 spring-security-saml 在应用程序中没有配置 IDP 错误

在 Grails 中使用 Pre/Post Spring-Security Annotations