在浏览器中存储JWT的位置? 如何防止CSRF?
我知道基于cookie的authentication。 可以应用SSL和HttpOnly标志来保护来自MITM和XSS的基于cookie的身份validation。 但是,为了保护CSRF,需要采取更多的特殊措施。 他们只是有点复杂。 ( 参考 )
最近,我发现JSON Web Token(JWT)作为authentication的解决scheme非常热门。 我知道关于编码,解码和validationJWT的东西。 但是,我不明白为什么一些网站/教程告诉我们如果使用JWT就不需要CSRF保护。 我读了很多,试图总结下面的问题。 我只希望有人能够提供智威汤逊的全貌,并澄清我误解智威汤逊的概念。
-
如果JWT存储在cookie中,我认为它与基于cookie的authentication相同,除了服务器不需要有会话来validationcookie /令牌。 如果没有采取特殊措施,CSRF仍然存在风险。 JWT是不是存储在cookie中?
-
如果JWT存储在localStorage / sessionStorage中,那么没有cookie就不需要防止CRSF。 问题是如何将JWT发送到服务器。 我在这里发现build议使用jQuery通过Ajax请求的HTTP头发送JWT。 那么,只有ajax请求可以进行身份validation?
-
另外,我还发现有更多的博客使用“Authorization header”和“Bearer”来发送JWT。 我不明白博客谈论的方法。 请问有人可以解释更多关于“授权标题”和“承载者”吗? 这是否使JWT通过所有请求的HTTP头传输? 如果是的话,CSRF呢?
JWT令牌很stream行,因为它们被用作OAuth 2.0和OpenID Connect等新授权和authentication协议中的默认令牌格式。
当令牌存储在cookie中时,浏览器会自动将其与每个请求一起发送到同一个域,这仍然容易受到CSRF攻击。
承载authentication是HTTP中定义的authenticationscheme之一。 它基本上意味着YOU
将(JWT)令牌粘贴在请求的Authorization HTTP标头中。 浏览器不会自动为你做这个,所以它不适合保护你的网站。 由于浏览器不会自动将头添加到您的请求,它不容易受到CSRF攻击,这取决于您的身份validation信息被自动提交到原始域。
承载scheme通常用于保护通过AJAX调用或移动客户端使用的Web API(REST服务)。
我们需要将JWT存储在客户端计算机上。 如果我们将它存储在LocalStorage / SessionStorage中,那么它很容易被XSS攻击抓取。 如果我们将它存储在cookies中,那么黑客可以在CSRF攻击中使用它(不读取它),并模拟用户并联系我们的API,并发送请求来执行操作或代表用户获取信息。
但是有几种方法可以保证JWT在cookies中不被盗取(但仍然有一些先进的技术可以窃取它们)。 但是如果你想依赖LocalStorage / SessionStorage,那么可以通过一个简单的XSS攻击来访问它。
所以为了解决CSRF问题,我在我的应用程序中使用了Double Submit Cookies。
双重提交Cookie方法
-
将JWT存储在HttpOnly Cookie中,并以安全模式将其用于通过HTTPS进行传输。
-
请求中的大部分CSRF攻击与原始主机有不同的来源或引用标头。 因此,请检查标题中是否有任何内容,是否来自您的域名! 如果不拒绝他们。 如果请求中既没有起源地址又没有引用地址,则不用担心。 您可以依靠我在下一步中解释的X-XSRF-TOKEN头部validation结果。
-
虽然浏览器会自动为请求的网域提供Cookie,但有一个有用的限制:在网站上运行的JavaScript代码无法读取其他网站的Cookie。 我们可以利用这个来创build我们的CSRF解决scheme。 为了防止CSRF攻击,我们必须创build一个额外的Javascript可读cookie,称为:XSRF-TOKEN。 这个cookie必须在用户login时创build,并且应该包含一个随机的,不可猜测的string。 我们还将这个数字作为私人索赔存储在智威汤逊本身。 每当JavaScript应用程序想要发出请求时,都需要读取该令牌并将其发送到自定义HTTP头中。 因为这些操作(读取cookie,设置标题)只能在JavaScript应用程序的同一个域上完成,所以我们可以知道这是由正在使用我们的JavaScript应用程序的真实用户完成的。
Angular JS让你的生活变得轻松
幸运的是,我在我们的平台中使用了Angular JS,Angular包装了CSRF令牌方法,使我们更容易实现。 对于我们的Angular应用程序对服务器所做的每个请求,Angular $http
服务都会自动执行这些操作:
- 在当前域中查找名为XSRF-TOKEN的cookie。
- 如果find该cookie,它将读取该值并将其作为X-XSRF-TOKEN标头添加到请求中。
这样客户端的实现就自动处理了! 我们只需要在服务器端的当前域上设置一个名为XSRF-TOKEN
的cookie,当我们的API从客户端获得任何调用时,它必须检查X-XSRF-TOKEN
头并将其与JWT中的XSRF-TOKEN
进行比较。 如果他们匹配,那么用户是真实的。 否则,这是一个伪造的请求,你可以忽略它。 这种方法受“双重提交Cookie”方法的启发。
警告
实际上,您仍然容易受到XSS的攻击,只是攻击者无法窃取JWT令牌供以后使用,但他仍然可以使用XSS代表您的用户发出请求。
无论您将JWT存储在localStorage
还是将您的XSRF令牌存储在非HttpOnly cookie中,都可以通过XSS轻松获取。 即使是HttpOnly cookie中的JWT,也可以通过像XST方法这样的高级XSS攻击来抓取。
所以除了双重提交Cookie方法之外,您还必须始终遵循针对XSS的最佳做法,包括转义内容。 这意味着删除任何可能导致浏览器执行您不想要的操作的代码。 通常这意味着删除// <![CDATA[
标签和HTML属性,导致JavaScript被评估。
在这里阅读更多:
- Angular的XSRF:它是如何工作的
- 在哪里存储您的智威汤逊 – cookies与HTML5networking存储