安全地实施CSRF免费JWT认证

时间:2016-08-26 12:16:42

标签: javascript php cookies csrf jwt

我刚刚了解了JWT的身份验证。在localStorage / sessionStorage中存储JWT令牌会暴露给XSS。将其存储在cookie中很容易受到CSRF的攻击。我一直在研究这个,我想到了这个解决方案,但我不确定这有多安全,如果我应该在生产中使用它。

解决方案是从服务器获取JWT令牌,将其存储在cookie中。生成将与每个HTML页面一起发送的CSRF令牌(将存储在JWT中),作为全局JS变量()的隐藏HTML字段。使用JS / AJAX时,每个请求都会发送该CSRF令牌。这样我们就可以先排除CSRF,然后验证JWT令牌。

我不确定是否应该为每个加载的页面发送新令牌,或者每个会话应该保留一个令牌。第一种情况意味着只有最后加载的页面/表单才能提交(如果用户打开了其他页面的多个选项卡,这可能会有问题。)

这是否可以在生产中使用?

此外,还有哪些其他解决方案可以达到同一目标?

1 个答案:

答案 0 :(得分:0)

以下是我对此问题的理解。

  • JWT令牌 - 存储在httponly / secure cookie中 - 这可确保任何Javascript无法访问它
  • CSRF令牌 - 由JS存储 - 登录时,将声明附加为标题(包括您的CSRF值)

当JS获取标头时,它可以将声明存储在cookie,localstorage或会话存储中。因为没有JS可以访问cookie中的JWT令牌,所以通过在每个请求中附加CSRF并确保它与JWT中的内容匹配,您确保它是您的JS发送的请求并发出令牌是你的后端。

隐藏字段不是一个很好的解决方案,因为您必须将其添加到每个请求中。根据您正在使用的框架,您应该能够将CSRF令牌加载到负责在刷新页面时将令牌作为标头发送到每个请求的任何内容上。在本地存储或cookie中拥有所有声明的好处是您可以保留用户前端状态。拥有exp声明意味着您可以告诉用户何时不再在安全jwt令牌cookie中拥有有效令牌,并且您可以重定向到登录页面。

  • sessionstorage - 仅适用于标签
  • localstorage - 特定于跨标签的域
  • cookie - 特定于跨标签的域

将CSFR添加到AJAX请求:

    $.ajax({
        type:"POST",
        beforeSend: function (request)
        {
            request.setRequestHeader("CSRF-TOKEN", csrfToken);
        },
        url: "entities",
        data: "json=" + escape(JSON.stringify(createRequestObject)),
        processData: false,
        success: function(msg) {
            $("#results").append("The result =" + StringifyPretty(msg));
        }
});

即使你不使用Angular,这仍然适用。您应该将标记附加到JS的标题中,并且可以从cookie中获取该值。

来自Angular JS Documentation

  

执行XHR请求时,$ http服务从cookie中读取令牌(默认情况下为XSRF-TOKEN),并将其设置为HTTP头(X-XSRF-TOKEN)。由于只有在您的域上运行的JavaScript才能读取Cookie,因此您的服务器可以确保XHR来自您域上运行的JavaScript。