Java CSRF:为每个请求生成令牌

Java CSRF:为每个请求生成令牌,java,jsp,spring-security,csrf,Java,Jsp,Spring Security,Csrf,现在,每个会话都有csrf令牌。并使用隐藏字段添加此标记jsp。以下代码段仅为每个会话提供一个: token = (String) session.getAttribute(CSRF_TOKEN_FOR_SESSION_NAME); if (null==token) { token = UUID.randomUUID().toString(); session.setAttribute(CSRF_TOKEN_FOR_SESSION_NAME, token)

现在,每个会话都有csrf令牌。并使用隐藏字段添加此标记jsp。以下代码段仅为每个会话提供一个:

token = (String) session.getAttribute(CSRF_TOKEN_FOR_SESSION_NAME);
    if (null==token) {
        token = UUID.randomUUID().toString();
        session.setAttribute(CSRF_TOKEN_FOR_SESSION_NAME, token);
    }
对于每一个请求

//calls the above snippet and this time token will not be null 
String st = CSRFTokenManager.getTokenForSession(request.getSession());
String rt = CSRFTokenManager.getTokenFromRequest(request);
这里,usings等于比较字符串并返回true或false

我的问题是,如果我尝试为每个请求生成令牌而不从会话获取令牌,会发生什么。在比较过程中,我将从会话和请求中获得。这是个好主意还是遗漏了什么

我不使用上面的代码片段,而是使用以下代码

    //for every request generate a new and set in session
    token = UUID.randomUUID().toString();
    session.setAttribute(CSRF_TOKEN_FOR_SESSION_NAME, token);

    //get the token from session and request and compare
    String st = (String) request.getSession().getAttribute("CSRF_TOKEN_FOR_SESSION_NAME");
    String rt = CSRFTokenManager.getTokenFromRequest(request);

您将想要翻转您上面所述的流程。在每次比较之后,您应该创建一个新的令牌

每个请求使用令牌的一个大缺点是,如果用户在浏览器中点击后退按钮:

  • 用户访问第1页并在会话中存储
    TokenA
  • 用户单击指向第2页的链接,提交
    TokenA
    。应用程序在会话中验证
    TokenA
    ,并向用户提供
    TokenB
  • 用户点击后退按钮返回第1页,会话信息不更新
  • Page1仍然只有
    TokenA
    的信息,用户单击链接或提交表单到Page3提交
    TokenA
    ,但会话只知道
    TokenB
  • 应用程序认为这是CSRF攻击

因此,您需要特别注意令牌的更新方式和更新时间。

除了Jay建议的解决方案外,我建议您通过在对客户端的响应中设置各种缓存控制头来避免缓存网页。

您可以生成令牌,而不必将其存储在会话中。将其作为隐藏字段添加到表单并作为cookie添加。当你收到请求时,比较字段和cookie的值。不确定..但是,我认为cookie容易受到CSRF攻击@user1609085。CSRF令牌的概念是攻击者试图发送“隐藏”请求,模仿另一个用户A。攻击者使用其他网站,在那里他可以注入一些恶意javascript代码,这里重要的是,他不能从这个网站发送cookie或特殊标题中的令牌(浏览器不允许攻击者这样做),这就是为什么令牌通常被放在那里。我需要在我的应用程序中使用这种类型的配置,请建议我使用这种类型的配置,我是否可以实现。嗨,我知道这是一篇老文章,但我现在也遇到了同样的情况。请验证我的理解:1)当用户访问第1页时,String st=(String)request.getSession().getAttribute(“CSRF_TOKEN_代表会话_NAME”);被调用且为空。在这个字符串之后,rt=CSRFTokenManager.getTokenFromRequest(请求);调用,它生成并为会话属性设置一个新值。比较什么时候完成?如果用户刷新页面会发生什么?没有上下文,我认为你的建议很糟糕。Jay描述的流程实际上根本不实用。GET请求99%的时间都不会更新数据,这就是为什么GET请求会更新数据的原因。如果GET请求更新了数据,则说明您的系统设计不好。所以你最后只保护帖子|放|删|头。。。对于那些从表单提交的用户来说,后退按钮的情况在设计良好的应用程序中并不常见。通常在发布表单后,您会重定向表单,以便在返回浏览器历史记录时无法重新发布表单