使用 CSRF 登录后如何启用 Spring Security POST 重定向?

Posted

技术标签:

【中文标题】使用 CSRF 登录后如何启用 Spring Security POST 重定向?【英文标题】:How to enable Spring Security POST redirect after log in with CSRF? 【发布时间】:2014-03-24 08:55:50 【问题描述】:

我正在使用带有 CSRF 的 Spring Security 3.2。我的配置包括:

  <csrf />
  <form-login default-target-url="/defaultPage"/>

当用户进行需要身份验证的 POST 表单提交(使用 CSRF 令牌)时,他将被重定向到登录页面。之后,Spring Security 将用户重定向到defaultPage,而不是提交请求。

我怀疑问题是 CSRF 令牌在登录期间被重置。

登录工作后如何获得这样的POST重定向?

更新:我尝试创建自定义 SavedRequestAwareAuthenticationSuccessHandler 以重定向到原始 POST 请求。但是,我看到原始请求甚至没有保存在 requestCache 中。

【问题讨论】:

我很想听听这个问题的答案。解释如何使用 Spring Security 实现它,或者可能解释它本质上是不安全的,因此不应该/不能使用 Spring Security 来完成。 【参考方案1】:

似乎启用CSRF保护时,如果请求使用GET方法,Spring Security只会将您的原始请求放在requestCache中。为了让它也缓存POST 请求,我创建了一个自定义requestCache

我不是 100% 相信这样做不会以某种方式削弱 CSRF 保护,但在我看来这似乎是安全的。

将请求缓存 bean 添加到 XML 配置中:

<bean id="requestCache" class="a.b.c.AlwaysSaveRequestCache" />

<http>
   <csrf />
   <request-cache ref="requestCache" />
</http>

通过扩展和借用HttpSessionRequestCache的代码来实现自定义请求缓存:

public class AlwaysSaveRequestCache extends HttpSessionRequestCache

   @Override
   public void saveRequest(HttpServletRequest request, HttpServletResponse response)
   
      final String SAVED_REQUEST = "SPRING_SECURITY_SAVED_REQUEST";
      DefaultSavedRequest savedRequest = new DefaultSavedRequest(request, new PortResolverImpl());
      request.getSession().setAttribute(SAVED_REQUEST, savedRequest);
      logger.debug("DefaultSavedRequest added to Session: " + savedRequest);
   

您的POST 请求现在应该被缓存并在被登录表单中断后重新发送。

【讨论】:

请注意,您可能并不总是希望将 POST 保存到请求缓存中,因为它可能会导致此处描述的问题:***.com/questions/4854480/…。我正在研究使用这种“AlwaysSaveRequestCache”的变体,它只允许保存 POST 请求 URL 的白名单(除了默认的请求匹配器行为)。【参考方案2】:

这很简单。不要以隐藏的形式传递 CSRF 令牌,它不会起作用将 CSRF token 直接作为 query params 传递给 URL,如下所示

<c:url value="/jobseeker/resume/uploadJobSeekerResume1?$_csrf.parameterName=$_csrf.token" var="uploadResumeURL"/>
 <form:form action="$uploadResumeURL" method="post" enctype="multipart/form-data">
                            <input id="file" name="file" type="file" />
                            <div class="modal-footer">
                            <button type="submit"  class="btn btn-success" >
                                <span class="glyphicon glyphicon-ok-sign"></span>&nbsp;Save
                            </button>

                        </div>
                        </form:form>

【讨论】:

【参考方案3】:

这是因为 HttpSessionRequestCache 和 DefaultSavedRequest 不是为使用“multipart/form-data”而设计的。多部分请求被视为常规请求,所有表单数据都将丢失。从 SavedRequest 恢复的请求将只包含 URL 和方法。

【讨论】:

【参考方案4】:

我可能有些不明白...但是你不能从你的配置中删除 default-target-url 吗?

【讨论】:

如果不指定目标url,Spring Security会重定向到域“/”的根目录,而不是提交之前的请求。启用/使用 CSRF 保护时会发生此问题。 GET 请求不会发生这种情况(没有 CSRF 令牌)。

以上是关于使用 CSRF 登录后如何启用 Spring Security POST 重定向?的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Security 中启用 CSRF 时,访问被拒绝 403

Springs CSRF 保护 HTML *only* 登录页面

如何在 JSF-Spring 集成应用中启用 CSRF 保护

Spring Rest Service - 当我尝试登录时,CSRF 令牌无效

Spring 未在响应时发送 CSRF 令牌

spring 如何使用 _csrf 参数或 X-CSRF-TOKEN 标头在内部验证 csrf 令牌?