CSRF:为每个请求生成令牌

时间:2013-05-01 16:20:09

标签: 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);
    }

并且针对每个请求,

//calls the above snippet and this time token will not be null 
String st = CSRFTokenManager.getTokenForSession(request.getSession());
String rt = CSRFTokenManager.getTokenFromRequest(request);

这里,usings equals比较字符串并返回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);

2 个答案:

答案 0 :(得分:5)

您需要翻转上述流程。每次比较后,您都应该创建一个新令牌。

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

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

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

答案 1 :(得分:-1)

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