Spring如何将新的_csrf标记添加到会话变量中?

时间:2016-05-17 20:48:02

标签: java spring spring-mvc spring-security spring-oauth2

当有人在Spring OAuth2(Source code for the API at this link)中执行POST/oauth/authorize时,CSRF令牌会在服务器上更新。

可以使用哪些特定的代码语法:
1.)在代码中访问新创建的CSRF令牌?
2.)将新铸造的CSRF令牌的副本分配给惰性会话变量?
3.)随后检索新的会话变量以便在另一个类中使用?

此要求的上下文是一个控制流,涉及通过多个过滤器和控制器进行变量路由,同时用户通过/oauth/authorize端点进行多次传递。变量需要保存到会话范围,然后从会话范围中检索,并根据算法的需要放回到请求范围内。

可能需要创建和使用上述会话变量的类的示例包括:

1。)任何有@Controller annotation
的班级 2.)OncePerRequestFilter的任何自定义实现,
3.)DefaultOAuth2RequestFactory的任何自定义实现,
4.)和自定义过滤器链中使用的其他类型的类。

这可能是Spring MVC问题或Spring Security问题,或两者兼而有之,即使它涉及Spring OAuth2 API,其源代码是从Spring MVC和Spring Security构建的。

2 个答案:

答案 0 :(得分:2)

Spring Security文档详细介绍了这一点。您可以使用标题Include the CSRF Token部分来访问令牌。本节摘要:

  • 解决此问题的一种方法是使用_csrf请求属性来获取当前的CsrfToken 。使用JSP执行此操作的示例如下所示:
<c:url var="logoutUrl" value="/logout"/>
<form action="${logoutUrl}"
    method="post">
<input type="submit"
    value="Log out" />
<input type="hidden"
    name="${_csrf.parameterName}"
    value="${_csrf.token}"/>
</form>
  • 如果您使用的是Spring MVC <form:form>代码或Thymeleaf 2.1+并且正在使用@EnableWebSecurity,则CsrfToken将自动包含在您的内容中(使用CsrfRequestDataValueProcessor)。有关详细信息,请参阅Automatic Token Inclusion
  • Spring Security提供CsrfTokenResolver,它可以自动解析Spring MVC参数的当前CsrfToken。通过使用@EnableWebSecurity,您将自动将其添加到Spring MVC配置中。如果您使用基于XML的配置,则必须自己添加。

正确配置CsrfTokenResolver后,您可以将CsrfToken公开给基于HTML的静态应用程序。

@RestController
public class CsrfController {

    @RequestMapping("/csrf")
    public CsrfToken csrf(CsrfToken token) {
        return token;
    }
}

保持CsrfToken对其他域的秘密非常重要。这意味着如果您使用的是跨域共享(CORS),则不应将CsrfToken暴露给任何外部域。

答案 1 :(得分:0)

这是OP要求的:

1。)按如下方式检索CSRF令牌:

ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
CsrfToken csrf = (CsrfToken) attr.getRequest().getAttribute(CsrfToken.class.getName());

2。)然后用令牌做任何你想做的事。 (轻轻一点,知道你在做什么,这样你就不会弄得一团糟。)或许把csrf标记放在一个类代码中的惰性会话变量中并保留在那里,直到需要将它拉出来一个不同的类代码。

3.)然后(可能在控制流程中的其他类别的代码中)将令牌放回请求中,如下所示:

attr.setAttribute("_csrf", csrf, RequestAttributes.SCOPE_REQUEST);
RequestContextHolder.setRequestAttributes(attr);

以上内容将用于清除自定义处理的副作用。例如,保存旧请求然后在DefaultOAuth2RequestFactoryOncePerRequestFilter的自定义实现中重新使用,但csrf令牌值在旧时间之间发生更改的情况请求的创建和新请求,以便在将旧csrf值添加到控制流中之前,需要在旧请求中更新dataServiceOne值。