我'm trying to implement JWT in my authentication system and I have a few questions. To store the token, I could use cookies but it'也可以使用 localStorage
或 sessionStorage
.
哪个是最好的选择?
我已经读过JWT保护网站免受CSRF的侵害 . 但是,我无法想象假设我将JWT令牌保存在cookie存储中会如何工作 .
那么它将如何保护CSRF?
Update 1
我看到了一些如下用法示例:
curl -v -X POST -H "Authorization: Basic VE01enNFem9FZG9NRERjVEJjbXRBcWJGdTBFYTpYUU9URExINlBBOHJvUHJfSktrTHhUSTNseGNh"
当我从浏览器向服务器发出请求时,如何实现?我还看到有些人在URL中实现了令牌:
http://exmple.com?jwt=token
如果我通过AJAX发出请求,那么我可以设置一个像 jwt: [token]
的 Headers 然后我可以从 Headers 中读取标记 .
Update 2
我安装了高级REST客户端谷歌浏览器扩展,并能够将令牌作为自定义标头传递 . 在向服务器发出GET请求时,是否可以通过Javascript设置此标头数据?
3 回答
看看这个网站:https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
如果要存储它们,则应使用localStorage或sessionStorage(如果可用)或cookie . 您还应该使用Authorization标头,但不使用Basic方案,而是使用Bearer one:
使用JS,您可以使用以下代码:
选择存储更多的是权衡,而不是试图找到明确的最佳选择 . 我们来看几个选项:
选项1 - Web存储(localStorage或sessionStorage)
优点
浏览器不会自动包含从Web存储到HTTP请求的任何内容,使其容易受到CSRF的影响
只能通过在创建数据的完全相同的域中运行的Javascript来访问
允许使用最语义正确的方法在HTTP中传递令牌身份验证凭据(带有
Bearer
方案的Authorization
标头)很容易挑选应该包含身份验证的请求
缺点
无法通过在创建数据的子域中运行的Javascript访问_(
example.com
无法读取example.com
所写的值)⚠️易受XSS攻击
为了执行经过身份验证的请求,您只能使用允许自定义请求的浏览器/库API(在
Authorization
标头中传递令牌)用法
您可以利用浏览器localStorage或sessionStorage API在执行请求时存储然后检索令牌 .
选项2 - 仅HTTP的cookie
优点
这是 not 易受XSS攻击
浏览器会自动在满足cookie规范的任何请求中包含令牌(域,路径和生命周期)
可以在顶级域创建cookie,并将其用于子域执行的请求
缺点
⚠️它容易受到CSRF的影响
您需要注意并始终考虑子域中cookie的可能用途
Cherry挑选应该包含cookie的请求是可行但更麻烦
您可能(仍然)遇到一些问题,浏览器处理cookie的方式差异很小
⚠️如果您不小心,可以实施易受XSS攻击的CSRF缓解策略
服务器端需要验证cookie以进行身份验证,而不是更合适的
Authorization
标头用法
您无需在客户端执行任何操作,因为浏览器会自动为您处理任何事情 .
选项3 - 服务器端忽略Javascript可访问的cookie
优点
这是 not 易受CSRF攻击( because it's ignored by the server )
可以在顶级域创建cookie,并将其用于子域执行的请求
允许使用最语义正确的方法在HTTP中传递令牌身份验证凭据(带有
Bearer
方案的Authorization
标头)樱桃挑选应该包含身份验证的请求有点容易
缺点
⚠️它容易受到XSS的攻击
如果您不小心设置cookie的路径,那么浏览器会在请求中自动包含cookie,这将增加不必要的开销
为了执行经过身份验证的请求,您只能使用允许自定义请求的浏览器/库API(在
Authorization
标头中传递令牌)用法
您可以利用浏览器document.cookie API在执行请求时存储然后检索令牌 . 此API不像Web存储那样精细(你得到了所有的cookie)所以你需要额外的工作来解析你需要的信息 .
附加说明
这似乎是一个奇怪的选择,但它确实有一个很好的好处,你可以让存储可用于顶级域和所有子域,这是Web存储不会给你的东西 . 但是,实施起来更复杂 .
结论 - 最终说明
我的 recommendation for most common scenarios would be to go with Option 1 ,主要是因为:
如果您创建Web应用程序,则需要处理XSS;始终,独立于您存储令牌的位置
如果你不想担心的话
另请注意,基于cookie的选项也大不相同,因为选项3 cookie仅用作存储机制,因此它几乎就像是客户端的实现细节 . 但是,备选方案2意味着更传统的处理身份验证的方式;有关此cookie与令牌的进一步阅读,您可能会发现这篇文章很有趣:Cookies vs Tokens: The Definitive Guide .
最后,没有一个选项提到它,但当然必须使用HTTPS,这意味着应该适当地创建cookie以考虑到这一点 .
此博客文章对浏览器存储与Cookie进行了良好的并排比较,并解决了每种情况下的每次潜在攻击 . https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/
较短的答案/扰流板:cookie并在jwt中添加xsrf令牌 . 博客文章中的详细说明 .