Java Spring如何向会话变量添加新的_csrf令牌?

Java Spring如何向会话变量添加新的_csrf令牌?,java,spring,spring-mvc,spring-security,spring-oauth2,Java,Spring,Spring Mvc,Spring Security,Spring Oauth2,当有人在Spring OAuth2()中向/oauth/authorize发布时,服务器上的CSRF令牌将更新 可以使用什么特定的代码语法: 1.)在代码中访问新创建的CSRF令牌? 2.)将新生成的CSRF令牌的副本分配给惰性会话变量? 3.)随后检索新会话变量以在其他类中使用? 此要求的上下文是一个控制流,它涉及通过多个过滤器和控制器的可变路由,同时用户通过/oauth/authorize端点进行多次传递。变量需要保存到会话范围,然后根据算法的需要从会话范围检索并放回请求范围 可能需要创建和

当有人在Spring OAuth2()中向
/oauth/authorize
发布
时,服务器上的CSRF令牌将更新

可以使用什么特定的代码语法:
1.)在代码中访问新创建的CSRF令牌?
2.)将新生成的CSRF令牌的副本分配给惰性会话变量?
3.)随后检索新会话变量以在其他类中使用?

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

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

1.)任何带有,
2.)的任何自定义实现,
3.)的任何自定义实现,
4.)和自定义过滤器链中使用的其他类型的类


这可能是一个Spring MVC问题,也可能是一个Spring安全性问题,或者两者兼而有之,尽管它涉及Spring OAuth2 API,其源代码是由Spring MVC和Spring安全性构建的。

Spring安全性文档详细介绍了这一点。您可以使用节标题访问令牌。本节总结:

  • 一种方法是使用_csrfrequest属性获取当前CsrfToken。使用JSP执行此操作的示例如下所示:

  • 如果您使用的是Spring MVC
    标记或Thymeleaf 2.1+,并且使用的是
    @EnableWebSecurity
    ,则会自动为您包含
    CsrfToken
    (使用
    CsrfRequestDataValueProcessor
    )。有关详细信息,请参阅
  • 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公开给任何外部域。

这是OP要求的:

1.)检索CSRF令牌,如下所示:

ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
CsrfToken csrf = (CsrfToken) attr.getRequest().getAttribute(CsrfToken.class.getName());
attr.setAttribute("_csrf", csrf, RequestAttributes.SCOPE_REQUEST);
RequestContextHolder.setRequestAttributes(attr);
2.)然后对令牌执行任何操作。(小心踩,知道自己在做什么,以免弄乱。)也许可以将
csrf
标记放入一个类代码中的惰性会话变量中,并将其保留在那里,直到需要在另一个类代码中取出为止

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

ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
CsrfToken csrf = (CsrfToken) attr.getRequest().getAttribute(CsrfToken.class.getName());
attr.setAttribute("_csrf", csrf, RequestAttributes.SCOPE_REQUEST);
RequestContextHolder.setRequestAttributes(attr);

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

这并不能解决OP问题,尽管您的信息很有用,也很感激。我在同一篇文章中发布了一个单独的答案,其中包含了我认为是我在这篇文章中寻找的答案。你能评论一下它的安全性和适当性吗?