我刚刚了解了JWT的身份验证。将JWT令牌存储在localStorage/sessionStorage中是向XSS公开的。将其存储在cookie中容易受到CSRF的攻击。我一直在研究这个问题,我想出了这个解决方案,但我不确定这个方案有多安全,我是否应该在生产中使用它。
解决方案是从服务器获取JWT令牌,并将其存储在cookie中。生成一个CSRF令牌(将存储在JWT中),该令牌将与每个HTML页面一起发送,或者在隐藏的HTML字段中作为全局JS变量()发送。将使用JS/AJAX与每个请求一起发送CSRF令牌。这样,我们可以先排除CSRF,然后验证JWT令牌。
我不确定是否应该在每个加载的页面上发送一个新的令牌,或者每个会话都应该有一个令牌。第一种情况意味着只有最后加载的页面/表单才能提交(如果用户打开了其他页面的多个选项卡,则可能会出现问题)。
这是一个安全的解决方案,可以用于生产吗?
此外,还有哪些其他解决方案可以实现相同的目标呢?
发布于 2016-08-26 14:26:42
这是我对这个问题的理解。
当JS获取消息头时,它可以将声明存储在cookie、本地存储或会话存储中。因为没有JS可以访问cookie中的JWT令牌,所以通过在每个请求中附加CSRF并确保它与JWT中的内容匹配,您将确保是您的JS发送了请求,并且是您的后端发出了该令牌。
隐藏字段不是很好的解决方案,因为您必须将其添加到每个请求中。根据使用的框架,在刷新页面时,您应该能够将CSRF令牌加载到任何负责将令牌作为头发送到每个请求的东西中。将所有声明保存在本地存储或cookie中的好处是可以保留用户前端状态。拥有exp声明意味着您可以知道用户何时不再在安全的jwt令牌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));
}
});即使你没有使用角度,这仍然适用。您应该将令牌作为头部附加到JS中,从cookie中获取该值是很好的。
来自角JS文档
在执行XHR请求时,$http服务从cookie (默认情况下,XSRF)读取令牌,并将其设置为header (XSRF)。因为只有在您的域中运行的JavaScript才能读取cookie,所以您的服务器可以确信XHR来自运行在您域中的JavaScript。
https://stackoverflow.com/questions/39166157
复制相似问题