我知道基于cookie的身份验证。SSL和HttpOnly标志可以应用于保护基于cookie的身份验证不受MITM和XSS的影响。然而,为了保护它不受CSRF的影响,还需要采取更多的特殊措施。它们只是有点复杂。(参考)

最近,我发现JSON Web Token (JWT)作为一种身份验证解决方案非常热门。我了解编码、解码和验证JWT的知识。然而,我不明白为什么有些网站/教程告诉我们,如果使用JWT,就不需要CSRF保护。我已经阅读了很多,并试图总结以下问题。我只是希望有人能提供一个关于JWT的更大的图景,并澄清我对JWT的误解。

If the JWT is stored in a cookie, I think it is the same as cookie-based authentication except that the server does not need to have sessions to verify the cookie/token. There is still a risk of CSRF if no special measure is implemented. Isn't JWT stored in a cookie? If the JWT is stored in localStorage/sessionStorage, then there is no cookie involved so don't need to protect against CSRF. The question is how to send the JWT to the server. I found here that it is suggested to use jQuery to send the JWT by HTTP header of ajax requests. So, only the ajax requests can do the authentication? Also, I found one more blog that points to use "Authorization header" and "Bearer" to send the JWT. I don't understand the method the blog talks about. Could someone please explain more about "Authorization header" and "Bearer"? Does this make the JWT transmitted by HTTP header of ALL requests? If yes, what about CSRF?


当前回答

JWT应该存储在cookie中。你可以根据需要使用httponly和secure标志。

为了防止CSRF,如果适合你的应用程序,同样的站点cookie属性可以设置为严格的-它将阻止你的站点的登录用户从任何其他站点跟踪到你的站点的任何链接。

恕我冒昧,CSRF保护应该与使用双重提交Cookie技术的身份验证分开进行:

在服务器上,生成一个随机字符串(csrf_token)并将其设置在cookie中。 在客户机上,获取cookie值并将其作为头值提交。 在服务器上,比较来自cookie和报头的值。它们应该匹配。

其他回答

将访问令牌存储在内存中,并将刷新令牌存储在cookie中

为什么这对CSRF是安全的?

虽然提交给/refresh_token的表单可以工作,并且将返回一个新的访问令牌,但如果攻击者使用的是HTML表单,则无法读取响应。为了防止攻击者成功地发出获取或AJAX请求并读取响应,这需要正确设置授权服务器的CORS策略,以防止来自未经授权的网站的请求。

你可以在这里阅读更多信息:

https://dev.to/cotter/localstorage-vs-cookies-all-you-need-to-know-about-storing-jwt-tokens-securely-in-the-front-end-15id

在web浏览器中,您可以将JWT存储在本地/会话存储或cookie中。两者都有弱点。您可以选择您喜欢的,但是您应该将安全性作为一个整体来保护,并且应该对过程进行良好的设计。如果您只防止XSRF和XSS,这将对您没有帮助。这是对你问题的简短回答。

首先要防止用户数据被窃取。非常有问题的是XSS攻击。如果您使用存储,攻击者可以窃取令牌-发送令牌到他的服务器,并请求窃取用户数据。如果你使用httpOnly cookie,他不能窃取令牌,但他可以发送请求(浏览器包含cookie,如果脚本在同一个域上),读取响应并将用户数据发送到他的服务器。结果都一样。

为了防止将数据发送到不同域的服务器,可以使用Content-Security-Policy报头。我建议学习所有的安全头和网络安全。好的资源是OWASP。这个论坛不是让你写很多页的。

XSRF (CSRF)

如果您使用cookie,那么应用程序很容易受到这种攻击。

如何预防:

设置httpOnly、secured和SameSite=strict标志。你也可以在没有httpOnly的情况下使用第二个cookie XSRF-TOKEN,并在头部X-Xsrf-Token中发送它的值。但如果浏览器支持,这是通过SameSite标志解决的。

XSS

Both storage and cookies are vulnerable to XSS in some meaning. With javascript code you can read storage and you can send requests to server with cookies included by browser as you are on the same domain. If you use user inputs, you should escape/sanitize them. You can also use header x-xss-protection. The most problematic is malicious code in 3rd party js libs as you cannot escape it and it runs on the same domain. You can prevent user data to be stolen by your mistake, but such code can cause different problems to your application and users.

JWT令牌很流行,因为在OAuth 2.0和OpenID Connect等新的授权和身份验证协议中,它们被用作默认的令牌格式。

当令牌存储在cookie中时,浏览器会自动将它与每个请求一起发送到同一个域,这仍然容易受到CSRF攻击。

承载身份验证是HTTP中定义的一种身份验证方案。它基本上意味着您将(JWT)令牌插入请求的授权HTTP报头中。浏览器不会自动为你做这些,所以它不适合保护你的网站。由于浏览器不会自动向您的请求添加标头,因此它不容易受到CSRF攻击,这取决于您的身份验证信息自动提交到原始域。

承载方案通常用于保护通过AJAX调用或移动客户端使用的web api (REST服务)。

现在在2020年,只需将JWT令牌存储在一个带有SameSite=strict的cookie中,就可以击败CSRF。当然,也要保持secure和httpOnly。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite

JWT应该存储在cookie中。你可以根据需要使用httponly和secure标志。

为了防止CSRF,如果适合你的应用程序,同样的站点cookie属性可以设置为严格的-它将阻止你的站点的登录用户从任何其他站点跟踪到你的站点的任何链接。

恕我冒昧,CSRF保护应该与使用双重提交Cookie技术的身份验证分开进行:

在服务器上,生成一个随机字符串(csrf_token)并将其设置在cookie中。 在客户机上,获取cookie值并将其作为头值提交。 在服务器上,比较来自cookie和报头的值。它们应该匹配。