我试图在我的身份验证系统中实现JWT,我有几个问题。要存储令牌,我可以使用Cookie,但也可以使用localStorage
或sessionStorage
。
哪个是最佳选择?
我已经读过JWT保护网站免受CSRF的侵害。但是,我无法想象假设我将JWT令牌保存在cookie存储中会如何工作。
那么它如何防止CSRF?
更新1
我看到了一些使用示例,如下所示:
curl -v -X POST -H "Authorization: Basic VE01enNFem9FZG9NRERjVEJjbXRBcWJGdTBFYTpYUU9URExINlBBOHJvUHJfSktrTHhUSTNseGNh"
当我从浏览器向服务器发出请求时,如何实现?我还看到有些人在URL中实现了令牌:
http://exmple.com?jwt=token
如果我通过AJAX发出请求,那么我可以设置一个像jwt: [token]
的标题然后我可以从标题中读取标记。
更新2
我安装了高级REST客户端Google Chrome扩展程序,并且能够将令牌作为自定义标头传递。在向服务器发出GET请求时,是否可以通过Javascript设置此标头数据?
答案 0 :(得分:80)
选择存储更多的是权衡,而不是试图找到明确的最佳选择。我们来看几个选项:
localStorage
或sessionStorage
)Authorization
方案的Bearer
标头)example.com
无法读取sub.example.com
写的值)Authorization
标头中传递令牌)您可以利用浏览器localStorage
或sessionStorage
API来存储,然后在执行请求时检索令牌。
localStorage.setItem('token', 'asY-x34SfYPk'); // write
console.log(localStorage.getItem('token')); // read
Authorization
标头您无需在客户端执行任何操作,因为浏览器会自动为您处理事情。
Authorization
方案的Bearer
标头)Authorization
标头中传递令牌)您可以利用浏览器document.cookie
API在执行请求时存储然后检索令牌。此API不像Web存储那样精细(您获得所有cookie),因此您需要额外的工作来解析所需的信息。
document.cookie = "token=asY-x34SfYPk"; // write
console.log(document.cookie); // read
这似乎是一个奇怪的选择,但它确实有一个很好的好处,你可以让存储可用于顶级域和所有子域,这是Web存储不会给你的东西。但是,实施起来更复杂。
我对大多数常见情况的建议是选择1 ,主要是因为:
另请注意,基于cookie的选项也大不相同,因为选项3 cookie仅用作存储机制,因此它几乎就像是客户端的实现细节。但是,备选方案2意味着更传统的处理身份验证的方式;有关此cookie与令牌的进一步阅读,您可能会发现这篇文章很有趣:Cookies vs Tokens: The Definitive Guide。
最后,没有一个选项提到它,但当然必须使用HTTPS,这意味着应该适当地创建cookie以考虑到这一点。
答案 1 :(得分:22)
请看这个网站:https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
如果要存储它们,则应使用localStorage或sessionStorage(如果可用)或cookie。 您还应该使用Authorization标头,但不使用Basic方案,而是使用Bearer one:
curl -v -X POST -H "Authorization: Bearer YOUR_JWT_HERE"
使用JS,您可以使用以下代码:
<script type='text/javascript'>
// define vars
var url = 'https://...';
// ajax call
$.ajax({
url: url,
dataType : 'jsonp',
beforeSend : function(xhr) {
// set header if JWT is set
if ($window.sessionStorage.token) {
xhr.setRequestHeader("Authorization", "Bearer " + $window.sessionStorage.token);
}
},
error : function() {
// error handler
},
success: function(data) {
// success handler
}
});
</script>
答案 2 :(得分:9)
此博客文章对浏览器存储与Cookie进行了良好的并排比较,并解决了每种情况下的每次潜在攻击。 https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/
较短的答案/剧透:cookies并在jwt中添加xsrf标记。博客文章中的详细解释。
答案 3 :(得分:4)
截至 2021 年,随着在当今大多数浏览器上为 cookie 引入了SameSite:松散/严格选项,事情发生了一些变化 >
所以要详细说明 João Angelo 的回答,我想说现在最安全的方法是:
使用以下选项将 JWT 存储在 cookie 中
这将同时避免 XSS 和 CSRF
答案 4 :(得分:0)
您应该从不,从将JWT存储在内存之外。
如果您要在一个较长的会话期间(例如令牌过期仅15分钟,则要保留1个小时)来保留JWT,则每当令牌即将过期时,静静地再次在后台登录用户。
如果要在会话之间持久保留JWT,则应使用刷新令牌。顺便说一句,顺便说一句,大部分时间也用于上述目的。您应该将其存储在HttpOnly cookie中(更确切地说,是通过Set-Cookie标头设置服务器,前端调用/ refresh_token API端点。)
刷新令牌BTW是最少的弊端;作为补充,您应该确保遵循最佳实践来减轻XSS。
localStorage,sessionStorage和cookie都具有漏洞。
这是我在JWT上阅读过的最好的指南: https://blog.hasura.io/best-practices-of-using-jwt-with-graphql/