简体   繁体   English

使用 ReactJS 将 JWT 存储在 localStorage 中是否安全?

[英]Is it safe to store a JWT in localStorage with ReactJS?

I'm currently building a single page application using ReactJS.我目前正在使用 ReactJS 构建单页应用程序。

I read that one of the reasons for not using localStorage is because of XSS vulnerabilities.我读到不使用localStorage的原因之一是因为 XSS 漏洞。

Since React escapes all user input, would it now be safe to use localStorage ?由于 React 会转义所有用户输入,现在使用localStorage是否安全?

In most of the modern single page applications, we indeed have to store the token somewhere on the client side (most common use case - to keep the user logged in after a page refresh).在大多数现代单页应用程序中,我们确实必须将令牌存储在客户端的某处(最常见的用例 - 以在页面刷新后保持用户登录)。

There are a total of 2 options available: Web Storage (session storage, local storage) and a client side cookie.共有 2 个选项可用:Web 存储(会话存储、本地存储)和客户端 cookie。 Both options are widely used, but this doesn't mean they are very secure.这两个选项都被广泛使用,但这并不意味着它们非常安全。

Tom Abbott summarizes well the JWT sessionStorage and localStorage security : Tom Abbott 很好地总结了JWT sessionStorage 和 localStorage 安全性

Web Storage (localStorage/sessionStorage) is accessible through JavaScript on the same domain. Web 存储 (localStorage/sessionStorage) 可通过同一域上的 JavaScript 访问。 This means that any JavaScript running on your site will have access to web storage, and because of this can be vulnerable to cross-site scripting (XSS) attacks .这意味着在您的站点上运行的任何 JavaScript 都可以访问 Web 存储,因此很容易受到跨站点脚本 (XSS) 攻击 XSS, in a nutshell, is a type of vulnerability where an attacker can inject JavaScript that will run on your page.简而言之,XSS 是一种漏洞,攻击者可以在其中注入将在您的页面上运行的 JavaScript。 Basic XSS attacks attempt to inject JavaScript through form inputs, where the attacker puts <script>alert('You are Hacked');</script> into a form to see if it is run by the browser and can be viewed by other users.基本的 XSS 攻击尝试通过表单输入注入 JavaScript,攻击者将<script>alert('You are Hacked');</script>放入表单中,以查看它是否由浏览器运行并可以被其他用户查看.

To prevent XSS, the common response is to escape and encode all untrusted data.为了防止 XSS,常见的反应是对所有不受信任的数据进行转义和编码。 React (mostly) does that for you! React(主要)为你做这件事! Here's a great discussion about how much XSS vulnerability protection is React responsible for .这是关于 React 负责多少 XSS 漏洞保护的精彩讨论

But that doesn't cover all possible vulnerabilities!但这并不能涵盖所有可能的漏洞! Another potential threat is the usage of JavaScript hosted on CDNs or outside infrastructure .另一个潜在威胁是使用托管在 CDN 或外部基础设施上的 JavaScript

Here's Tom again:又是汤姆:

Modern web apps include 3rd party JavaScript libraries for A/B testing, funnel/market analysis, and ads.现代网络应用程序包括用于 A/B 测试、漏斗/市场分析和广告的第三方 JavaScript 库。 We use package managers like Bower to import other peoples' code into our apps.我们使用像 Bower 这样的包管理器将其他人的代码导入我们的应用程序。

What if only one of the scripts you use is compromised?如果您使用的只有一个脚本遭到破坏怎么办? Malicious JavaScript can be embedded on the page, and Web Storage is compromised.恶意 JavaScript 可以嵌入到页面中,并且 Web 存储受到威胁。 These types of XSS attacks can get everyone's Web Storage that visits your site, without their knowledge.这些类型的 XSS 攻击可以在他们不知情的情况下获取访问您网站的每个人的 Web 存储。 This is probably why a bunch of organizations advise not to store anything of value or trust any information in web storage.这可能就是为什么许多组织建议不要在网络存储中存储任何有价值的东西或信任任何信息的原因。 This includes session identifiers and tokens.这包括会话标识符和令牌。

Therefore, my conclusion is that as a storage mechanism, Web Storage does not enforce any secure standards during transfer .因此,我的结论是,作为一种存储机制,Web Storage在传输过程中不强制执行任何安全标准 Whoever reads Web Storage and uses it must do their due diligence to ensure they always send the JWT over HTTPS and never HTTP.阅读和使用 Web Storage 的人必须尽职尽责,以确保他们始终通过 HTTPS 而不是 HTTP 发送 JWT。

I know this is an old question but according what @mikejones1477 said, modern front end libraries and frameworks escape the text giving you protection against XSS.我知道这是一个老问题,但根据@mikejones1477 所说,现代前端库和框架会转义文本,为您提供针对 XSS 的保护。 The reason why cookies are not a secure method using credentials is that cookies doesn't prevent CSRF when localStorage does (also remember that cookies are accessible by JavaScript too, so XSS isn't the big problem here), this answer resume why . cookie 不是使用凭据的安全方法的原因是 cookie 不会在 localStorage 阻止 CSRF(还要记住 cookie 也可以通过 JavaScript 访问,所以 XSS 不是这里的大问题),这个答案恢复了原因

The reason storing an authentication token in local storage and manually adding it to each request protects against CSRF is that key word: manual.将身份验证令牌存储在本地存储中并手动将其添加到每个请求以防止 CSRF 的原因是关键字:手动。 Since the browser is not automatically sending that auth token, if I visit evil.example and it manages to send a POST http://example.com/delete-my-account , it will not be able to send my authn token, so the request is ignored.由于浏览器不会自动发送该身份验证令牌,如果我访问evil.example并且它设法发送一个 POST http://example.com/delete-my-account ,它将无法发送我的身份验证令牌,所以请求被忽略。

Of course httpOnly is the holy grail but you can't access from reactjs or any js framework beside you still have CSRF vulnerability.当然 httpOnly 是圣杯,但你不能从 reactjs 或任何 js 框架访问,你仍然有 CSRF 漏洞。 My recommendation would be localstorage or if you want to use cookies make sure implemeting some solution to your CSRF problem like Django does .我的建议是 localstorage,或者如果您想使用 cookie,请确保像 Django 那样为您的 CSRF 问题实施一些解决方案。

Regarding with the CDN's make sure you're not using some weird CDN, for example CDN like Google or bootstrap provide, are maintained by the community and doesn't contain malicious code, if you are not sure, you're free to review.关于 CDN,请确保您没有使用一些奇怪的 CDN,例如 Google 或 bootstrap 提供的 CDN,由社区维护并且不包含恶意代码,如果您不确定,可以自由查看。

Basically it's OK to store your JWT in your localStorage.基本上可以将 JWT 存储在 localStorage 中。

And I think this is a good way.我认为这是一个好方法。 If we are talking about XSS, XSS using CDN, it's also a potential risk of getting your client's login/pass as well.如果我们谈论的是 XSS,使用 CDN 的 XSS,这也是获取客户登录/通行证的潜在风险。 Storing data in local storage will prevent CSRF attacks at least.将数据存储在本地存储中至少可以防止 CSRF 攻击。

You need to be aware of both and choose what you want.您需要了解两者并选择您想要的。 Both attacks it's not all you are need to be aware of, just remember: YOUR ENTIRE APP IS ONLY AS SECURE AS THE LEAST SECURE POINT OF YOUR APP.这两种攻击并不是您需要注意的全部,请记住:您的整个应用程序仅与您的应用程序的最不安全点一样安全。

Once again storing is OK, be vulnerable to XSS, CSRF,... isn't再次存储是可以的,容易受到 XSS、CSRF 的攻击,......不是

A way to look at this is to consider the level of risk or harm.看待这一点的一种方法是考虑风险或伤害的程度。

Are you building an app with no users, POC/MVP?您是否正在构建一个没有用户的应用程序,POC/MVP? Are you a startup who needs to get to market and test your app quickly?您是需要快速进入市场并测试您的应用程序的初创公司吗? If yes, I would probably just implement the simplest solution and maintain focus on finding product-market-fit.如果是的话,我可能会实施最简单的解决方案,并继续专注于寻找适合市场的产品。 Use localStorage as its often easier to implement.使用 localStorage 通常更容易实现。

Are you building a v2 of an app with many daily active users or an app that people/businesses are heavily dependent on.您是在构建具有许多日常活跃用户的应用程序的 v2,还是人们/企业严重依赖的应用程序。 Would getting hacked mean little or no room for recovery?被黑客入侵是否意味着很少或没有恢复空间? If so, I would take a long hard look at your dependencies and consider storing token information in an http-only cookie.如果是这样,我会仔细研究您的依赖关系,并考虑将令牌信息存储在仅限 http 的 cookie 中。

Using both localStorage and cookie/session storage have their own pros and cons.使用 localStorage 和 cookie/session 存储各有利弊。

As stated by first answer: If your application has an XSS vulnerability, neither will protect your user.如第一个答案所述:如果您的应用程序存在 XSS 漏洞,则两者都不会保护您的用户。 Since most modern applications have a dozen or more different dependencies, it becomes increasingly difficult to guarantee that one of your application's dependencies is not XSS vulnerable.由于大多数现代应用程序都有十几个或更多不同的依赖项,因此越来越难以保证应用程序的一个依赖项不受 XSS 攻击。

If your application does have an XSS vulnerability and a hacker has been able to exploit it, the hacker will be able to perform actions on behalf of your user.如果您的应用程序确实存在 XSS 漏洞并且黑客已经能够利用它,那么黑客将能够代表您的用户执行操作。 The hacker can perform GET/POST requests by retrieving token from localStorage or can perform POST requests if token is stored in a http-only cookie.黑客可以通过从 localStorage 检索令牌来执行 GET/POST 请求,或者如果令牌存储在仅 http 的 cookie 中,则可以执行 POST 请求。

The only down-side of the storing your token in local storage is the hacker will be able to read your token.将令牌存储在本地存储中的唯一缺点是黑客将能够读取您的令牌。

I'm disturbed by all the answers that suggest not to store in local storage as this is susceptible to an XSS attack or a malicious library.我对所有建议不要存储在本地存储中的答案感到不安,因为这很容易受到 XSS 攻击或恶意库的影响。 Some of these even go into long-winded discussions, even though the answer is pretty small/straightforward, which I'll get to shortly.其中一些甚至进入冗长的讨论,即使答案非常小/直截了当,我很快就会谈到。

Suggesting that is the equivalent of saying “Don't use a frying pan to cook your food because if you end up drunk one night and decide to fry, you'll end up burning yourself and your house”.建议这相当于说“不要用煎锅做饭,因为如果你最终喝醉了一晚并决定油炸,你最终会烧毁你自己和你的房子”。 If the jwt gets leaked due to an XSS attack or malicious library, then the site owner has a bigger problem: their site is susceptible to XSS attacks or is using a malicious library.如果 jwt 由于 XSS 攻击或恶意库而泄露,那么站点所有者就有一个更大的问题:他们的站点容易受到 XSS 攻击或正在使用恶意库。

The answer: if you're confident your site doesn't have those vulnerabilities, go for it.答案是:如果您确信您的网站没有这些漏洞,那就去做吧。

Ref: https://auth0.com/docs/security/data-security/token-storage#browser-local-storage-scenarios参考: https ://auth0.com/docs/security/data-security/token-storage#browser-local-storage-scenarios

It is not safe if you use CDN's:如果您使用 CDN 是不安全的:

Malicious JavaScript can be embedded on the page, and Web Storage is compromised.恶意 JavaScript 可以嵌入到页面中,并且 Web 存储受到威胁。 These types of XSS attacks can get everyone's Web Storage that visits your site, without their knowledge.这些类型的 XSS 攻击可以在他们不知情的情况下获取访问您网站的每个人的 Web 存储。 This is probably why a bunch of organizations advise not to store anything of value or trust any information in web storage.这可能就是为什么许多组织建议不要在网络存储中存储任何有价值的东西或信任任何信息的原因。 This includes session identifiers and tokens.这包括会话标识符和令牌。

via stormpath通过风暴路径

Any script you require from the outside could potentially be compromised and could grab any JWTS from your client's storage and send personal data back to the attacker's server.您需要从外部获取的任何脚本都可能受到威胁,并可能从您的客户端存储中获取任何 JWTS 并将个人数据发送回攻击者的服务器。

Localstorage is designed to be accessible by javascript, so it doesn't provide any XSS protection. Localstorage 设计为可通过 javascript 访问,因此它不提供任何 XSS 保护。 As mentioned in other answers, there is a bunch of possible ways to do an XSS attack, from which localstorage is not protected by default.正如其他答案中提到的,有很多可能的方法来进行 XSS 攻击,默认情况下本地存储不受保护。

However, cookies have security flags which protect from XSS and CSRF attacks.但是,cookie 具有防止 XSS 和 CSRF 攻击的安全标志。 HttpOnly flag prevents client side javascript from accessing the cookie, Secure flag only allows the browser to transfer the cookie through ssl, and SameSite flag ensures that the cookie is sent only to the origin. HttpOnly 标志防止客户端 javascript 访问 cookie,Secure 标志只允许浏览器通过 ssl 传输 cookie,SameSite 标志确保 cookie 仅发送到源。 Although I just checked and SameSite is currently supported only in Opera and Chrome, so to protect from CSRF it's better to use other strategies.虽然我刚刚检查过,SameSite 目前仅在 Opera 和 Chrome 中受支持,所以为了防止 CSRF,最好使用其他策略。 For example, sending an encrypted token in another cookie with some public user data.例如,在另一个 cookie 中发送带有一些公共用户数据的加密令牌。

So cookies are a more secure choice for storing authentication data.因此 cookie 是存储身份验证数据的更安全的选择。

One thing to keep in mind is whether the JWTs are:要记住的一件事是 JWT 是否是:

  • First party (ie. simply for accessing your own server commands)第一方(即仅用于访问您自己的服务器命令)
  • Third party (ie. a JWT for Google, Facebook, Twitter, etc.)第三方(即 Google、Facebook、Twitter 等的 JWT)

If the JWT is first-party:如果 JWT 是第一方:

Then it doesn't matter that much whether you store the JWT in local storage, or a secured cookie (ie. HttpOnly , SameSite=strict , and secure ) [assuming your site is already using HTTPS, which it should].那么无论您将 JWT 存储在本地存储还是安全 cookie(即HttpOnlySameSite=strictsecure )[假设您的站点已经使用 HTTPS,它应该] 都没有多大关系。

This is because, assuming an XSS attack succeeds (ie. an attacker was able to insert Javascript code through a JS dependency that is now running on all visitor browsers), it's "game over" anyway;这是因为,假设 XSS 攻击成功(即攻击者能够通过现在在所有访问者浏览器上运行的 JS 依赖项插入 Javascript 代码),无论如何它“游戏结束”; all the commands which were meant to be secured by the "JWT token verifications", can now be executed by the attacker just by having the script they've inserted into the frontend JS call all the needed endpoints.所有本应由“JWT 令牌验证”保护的命令现在都可以由攻击者执行,只需让他们插入到前端 JS 中的脚本调用所有需要的端点。 Even though they can't read the JWT token itself (because of the cookie's http-only flag), it doesn't matter because they can just send all the needed commands, and the browser will happily send the JWT token along with those commands.即使他们不能读取 JWT 令牌本身(因为 cookie 的 http-only 标志),也没有关系,因为他们可以发送所有需要的命令,浏览器会很高兴地发送 JWT 令牌和这些命令.

Now while the XSS-attack situation is arguably "game over" either way (whether local-storage or secured cookie), cookies are still a little better, because the attacker is only able to execute the attacks if/when the user has the website open in their browser.现在,尽管 XSS 攻击情况可以说是“游戏结束”(无论是本地存储还是安全 cookie),cookie 仍然好一点,因为攻击者只有在用户拥有网站时才能执行攻击在他们的浏览器中打开。

This causes the following "annoyances" for the attacker:这会给攻击者带来以下“烦恼”:

  1. "My XSS injection worked! Okay, time to collect private data on my boss and use it as blackmail. Dang it! He only ever logs in while I'm here at work. I'll have to prepare all my code ahead of time, and have it run within the three minutes he's on there, rather than getting to poke around into his data on the platform in a more gradual/exploratory way." “我的 XSS 注入成功了!好吧,是时候收集我老板的私人数据并将其用作勒索了。该死的!他只在我在这里工作时登录。我必须提前准备所有代码,并让它在他在那里的三分钟内运行,而不是以更渐进/探索性的方式在平台上查看他的数据。”
  2. "My XSS injection worked! Now I can change the code to send all Bitcoin transfers to me instead! I don't have any particular target in mind, so I don't need to wait for anyone. Man though, I wish I could access the JWT token itself -- that way I could silently collect them all, then empty everyone's wallets all at once. With these cookie-protected JWTs, I may only be able to hijack a few dozen visitors before the devs find out and suspend transfers..." “我的 XSS 注入成功了!现在我可以更改代码以将所有比特币转账发送给我!我没有任何特定的目标,所以我不需要等待任何人。不过,我希望我能访问 JWT 令牌本身——这样我可以默默地收集它们,然后一次清空每个人的钱包。有了这些受 cookie 保护的 JWT,我可能只能在开发人员发现并暂停传输之前劫持几十个访问者……”
  3. "My XSS injection worked! This'll give me access to even the data that only the admins can see. Hmmm, unfortunately I have to do everything through the user's browser. I'm not sure there's a realistic way for me to download those 3gb files using this; I start the download, but there are memory issues, and the user always closes the site before it's done! Also, I'm concerned that client-side retransfers of this size might get detected by someone." “我的 XSS 注入成功了!这甚至可以让我访问只有管理员才能看到的数据。嗯,不幸的是,我必须通过用户的浏览器完成所有操作。我不确定是否有可行的方法来下载这些数据3gb 文件使用这个;我开始下载,但存在内存问题,用户总是在完成之前关闭站点!另外,我担心这种大小的客户端重新传输可能会被某人检测到。

If the JWT is third-party:如果 JWT 是第三方:

In this case, it really depends on what the third-party JWTs allow the holder to do.在这种情况下,这实际上取决于第三方 JWT 允许持有者做什么。

If all they do is let someone "access basic profile information" on each user, then it's not that bad if attackers can access it;如果他们所做的只是让某人“访问每个用户的基本个人资料信息”,那么攻击者可以访问它还不错; some emails may leak, but the attacker could probably get that anyway by navigating to the user's "account page" where that data is shown in the UI.一些电子邮件可能会泄漏,但攻击者可能会通过导航到用户的“帐户页面”来获取该数据,该数据显示在 UI 中。 (having the JWT token just lets them avoid the "annoyances" listed in the previous section) (拥有 JWT 令牌只是让他们避免上一节中列出的“烦恼”)

If, instead, the third-party JWTs let you do more substantial things -- such as have full access to their cloud-storage data, send out messages on third-party platforms, read private messages on third-party platforms, etc, then having access to the JWTs is indeed substantially worse than just being able to "send authenticated commands".相反,如果第三方 JWT 让你做更多实质性的事情——比如完全访问他们的云存储数据、在第三方平台上发送消息、在第三方平台上阅读私人消息等,那么访问 JWT 确实比仅仅能够“发送经过身份验证的命令”更糟糕。

This is because, when the attacker can't access the actual JWT, they have to route all commands through your 1st-party server.这是因为,当攻击者无法访问实际的 JWT 时,他们必须通过您的第一方服务器路由所有命令。 This has the following advantages:这具有以下优点:

  1. Limited commands: Because all the commands are going through your server, attackers can only execute the subset of commands that your server was built to handle.有限的命令:因为所有命令都通过您的服务器,攻击者只能执行您的服务器为处理而构建的命令子集。 For example, if your server only ever reads/writes from a specific folder in a user's cloud storage, then the attacker has the same limitation.例如,如果您的服务器仅从用户云存储中的特定文件夹读取/写入,则攻击者具有相同的限制。

  2. Easier detection: Because all the commands are going through your server, you may be able to notice (through logs, sudden uptick in commands, etc.) that someone has developed an XSS attack.更容易检测:因为所有命令都通过您的服务器,您可能会注意到(通过日志、命令的突然增加等)有人开发了 XSS 攻击。 This lets you potentially patch it more quickly.这使您可以更快地修补它。 (if they had the JWTs themselves, they could silently be making calls to the 3rd-party platforms, without having to contact your servers at all) (如果他们自己有 JWT,他们可以默默地调用 3rd 方平台,而根本无需联系您的服务器)

  3. More ways to identify the attacker: Because the commands are going through your server, you know exactly when the commands are being made, and what ip-address is being used to make them.识别攻击者的更多方法:因为命令正在通过您的服务器,所以您确切地知道命令是在什么时候发出的,以及用来发出命令的 IP 地址。 In some cases, this could help you identify who is doing the attacks.在某些情况下,这可以帮助您确定谁在进行攻击。 The ip-address is the most obvious way, though admittedly most attackers capable of XSS attacks would be aware enough to use a proxy. ip-address 是最明显的方式,尽管不可否认,大多数能够进行 XSS 攻击的攻击者都足够了解使用代理。

    A more advanced identification approach might be to, say, have a special message pop up that is unique for each user (or, at least, split into buckets), of such a nature that the attacker (when he loads up the website from his own account) will see that message, and try to run a new command based on it.一种更高级的识别方法可能是,例如,弹出一个对每个用户都是唯一的特殊消息(或者,至少,分成多个桶),其性质使得攻击者(当他从他的网站加载网站时)自己的帐户)将看到该消息,并尝试基于它运行新命令。 For example, you could link to a "fake developer blog post" talking about some "new API" you're introducing, which allows users to access even more of their private data;例如,您可以链接到“假开发者博客文章”,谈论您正在引入的一些“新 API”,它允许用户访问更多的私人数据; the sneaky part is that the URL for that "new API" is different per user viewing the blog post , such that when the API is attempted to be used (against the victim), you know exactly who did it.鬼鬼祟祟的部分是,每个查看博客文章的用户的“新 API”的 URL 都不同,因此当尝试使用该 API(针对受害者)时,您确切知道是谁做的。 Of course, this relies on the idea that the attacker has a "real account" on the site alongside the victim, and could be tempted/fooled by this sort of approach (eg. it won't work if the attacker knows you're onto him), but it's an example of things you can do when you can intercept all authenticated commands.当然,这依赖于攻击者在受害者旁边的网站上拥有“真实帐户”的想法,并且可能会被这种方法诱惑/愚弄(例如,如果攻击者知道你是到他身上),但这是您可以拦截所有经过身份验证的命令时可以做的事情的一个例子。

  4. More flexible controlling: Lets say that you've just discovered that someone deployed an XSS attack on your site.更灵活的控制:假设您刚刚发现有人在您的站点上部署了 XSS 攻击。

    If the attackers have the 3rd-party JWTs themselves, your options are limited: you have to globally disable/reset your OAuth/JWT configuration for all 3rd-party platforms.如果攻击者自己拥有第 3 方 JWT,那么您的选择将受到限制:您必须全局禁用/重置所有第 3 方平台的 OAuth/JWT 配置。 This causes serious disruption while you try to figure out the source of the XSS attack, as no one is able to access anything from those 3rd-party platforms.当您试图找出 XSS 攻击的来源时,这会导致严重的中断,因为没有人能够从这些第 3 方平台访问任何内容 (including your own server, since the JWT tokens it may have stored are now invalid) (包括您自己的服务器,因为它可能存储的 JWT 令牌现在无效)

    If the JWT tokens are instead protected in http-only cookies, you have more options: You can simply modify your server to "filter out" any reads/writes that are potentially dangerous.如果 JWT 令牌在 http-only cookie 中受到保护,您有更多选择:您可以简单地修改您的服务器以“过滤掉”任何潜在危险的读取/写入。 In some cases added this "filtering" is a quick and easy process, allowing your site to continue in "read-only"/"limited" mode without disrupting everything;在某些情况下,添加此“过滤”是一个快速而简单的过程,允许您的网站继续以“只读”/“受限”模式继续运行,而不会破坏一切; in other cases, things may be complex enough that it's not worth trusting the filter code for security.在其他情况下,事情可能非常复杂,以至于不值得信任过滤器代码的安全性。 The point though is that you have more options.关键是你有更多的选择。

    For example, maybe you don't know for sure that someone has deployed an XSS attack, but you suspect it.例如,也许你不确定有人部署了 XSS 攻击,但你怀疑它。 In this case, you may not want to invalidate the JWT tokens of every user (including those your server is using in the background) simply on the suspicion of an XSS attack (it depends on your suspicion level).在这种情况下,您可能不想仅仅因为怀疑 XSS 攻击(这取决于您的怀疑级别)而使每个用户(包括您的服务器在后台使用的那些)的 JWT 令牌无效。 Instead, you can just "make things read-only for a while" while you look into the issue more closely.相反,您可以在更仔细地研究问题时“将内容设置为只读一段时间”。 If it turns out nothing is wrong, you can just flip a switch and re-enable writes, without everyone having to log back in and such.如果事实证明一切正常,您只需拨动开关并重新启用写入,而无需每个人都重新登录等。

Anyway, because of these four benefits, I've decided to always store third-party JWTs in "secured cookies" rather than local storage.无论如何,由于这四个好处,我决定始终将第三方 JWT 存储在“安全 cookie”而不是本地存储中。 While currently the third-party JWTs have very limited scopes (such that it's not so big a deal if they are stolen), it's good future-proofing to do this, in case I'd like my app to request access to more privileged functionalities in the future (eg. access to the user's cloud storage).虽然目前第三方 JWT 的范围非常有限(因此如果它们被盗也没什么大不了的),这样做是很好的未来证明,以防我希望我的应用程序请求访问更多特权功能将来(例如访问用户的云存储)。

Note: The four benefits above (for storing third-party JWTs in secured cookies) may also partially apply for first-party JWTs, if the JWTs are used as authentication by multiple backend services, and the domains/ip-addresses of these other servers/services are public knowledge.注意:如果JWT 被多个后端服务用作身份验证,以及这些其他服务器的域/IP 地址,上述四个好处(用于将第三方 JWT 存储在安全 cookie 中)也可能部分适用于第一方 JWT /服务是公共知识。 In this case, they are "equivalent to third-party platforms", in the sense that "http-only cookies" restrict the XSS attacker from sending direct commands to those other servers, bringing part of the benefits of the four points above.在这种情况下,它们“相当于第三方平台”,从某种意义上说,“http-only cookie”限制了 XSS 攻击者向其他服务器发送直接命令,从而带来了上述四点的部分好处。 (it's not exactly the same, since you do at least control those other servers, so you can activate read-only mode for them and such -- but it'll still generally be more work than making those changes in just one place) (这不完全一样,因为您至少控制了其他服务器,因此您可以为它们激活只读模式等 - 但它通常仍然比在一个地方进行这些更改要多)

Isn't neither localStorage or httpOnly cookie acceptable? localStorage 或 httpOnly cookie 都不可接受吗? In regards to a compromised 3rd party library, the only solution I know of that will reduce / prevent sensitive information from being stolen would be enforced Subresource Integrity .关于受损的 3rd 方库,我所知道的唯一可以减少/防止敏感信息被盗的解决方案是强制执行Subresource Integrity

Subresource Integrity (SRI) is a security feature that enables browsers to verify that resources they fetch (for example, from a CDN) are delivered without unexpected manipulation.子资源完整性 (SRI) 是一种安全功能,使浏览器能够验证它们获取的资源(例如,从 CDN 获取的资源)是否在没有意外操作的情况下交付。 It works by allowing you to provide a cryptographic hash that a fetched resource must match.它通过允许您提供获取的资源必须匹配的加密哈希来工作。

As long as the compromised 3rd party library is active on your website, a keylogger can start collecting info like username, password, and whatever else you input into the site.只要受感染的第 3 方库在您的网站上处于活动状态,键盘记录器就可以开始收集用户名、密码以及您在网站中输入的任何其他信息等信息。

An httpOnly cookie will prevent access from another computer but will do nothing to prevent the hacker from manipulating the user's computer. httpOnly cookie 将阻止来自另一台计算机的访问,但不会阻止黑客操纵用户的计算机。

TLDR; TLDR;

Both work, but using a cookie with httpOnly is way safer than using localStorage, as any malicious javascript code introduced by XSS can read localstorage.两者都可以,但使用带有httpOnly的 cookie比使用 localStorage 更安全,因为 XSS 引入的任何恶意 javascript 代码都可以读取 localstorage。

There's a useful article written by Dr. Philippe De Ryck which gives an insight into the true impact of vulnerabilities particularly XSS. Philippe De Ryck 博士撰写了一篇有用的文章,深入了解了漏洞尤其是 XSS 的真正影响。

This article is an eye opener!这篇文章让人大开眼界!

In a nutshell, primary concern of the developer should be to protect the web application against XSS and shouldn't worry too much about what type of storage area is used.简而言之,开发人员最关心的应该是保护 web 应用程序免受 XSS 攻击,不必太担心使用什么类型的存储区域。

Dr. Phillipe recommends the following 3 steps:菲利普博士推荐以下 3 个步骤:

  1. Don't worry too much about the storage area.不要太担心存储区域。 Saving an access token in localStorage area will save the developer a massive amount of time for development of next phases of the application.在 localStorage 区域中保存访问令牌将为开发人员节省大量时间用于开发应用程序的下一阶段。

  2. Review your app for XSS vulnerabilities.检查您的应用程序是否存在 XSS 漏洞。 Perform a through code review and learn how to avoid XSS within the scope of your templating framework.执行代码审查并了解如何在模板框架的 scope 中避免 XSS。

  3. Build a defense-in-depth mechanism against XSS.构建针对 XSS 的纵深防御机制。 Learn how you could further lock down your application.了解如何进一步锁定您的应用程序。 Eg utilising Content Security Policy (CSP) and HTML5 sandboxing.例如,利用内容安全策略 (CSP) 和 HTML5 沙盒。

Remember that once you're vulnerable to XSS then its game over!请记住,一旦您容易受到 XSS 的攻击,那么它的游戏就结束了!

I'm coming late to the discussion, but with the advantage of more mature and modern auth protocols like OpenID Connect.我来晚了,但有更成熟和现代的身份验证协议(如 OpenID Connect)的优势。

TL;DR: The preferred method is to store your JWT Token in memory: not in a cookie, and not in localstorage. TL;DR:首选方法是将您的 JWT 令牌存储在 memory 中:不是在 cookie 中,也不是在本地存储中。

Details细节

You want to decouple the responsibility of authenticating users from the rest of the work your app does.您希望将验证用户身份的责任与您的应用程序所做的 rest 工作分离开来。 Auth is hard to get right, and the handful of teams that spend all their time thinking about this stuff can worry about the details you and I will never get right. Auth 很难做对,少数花费所有时间思考这件事的团队可能会担心你我永远做不对的细节。

Establish a dedicated Identity Provider for your app, and use the OpenID Connect protocol to authenticate with it.为您的应用程序建立专用的身份提供者,并使用 OpenID Connect 协议对其进行身份验证。 This could be a provider like Google, Microsoft, or Okta, or it could be a lightweight Identity Server that federates to one or more of those other services.这可能是像谷歌、微软或 Okta 这样的提供商,也可能是联合到一个或多个其他服务的轻量级身份服务器。

Use the Authorization Code Flow to let the user authenticate and get the access token to your app.使用授权代码流让用户进行身份验证并获取您应用程序的访问令牌。 Use a respected client library to handle the OpenID Connect details, so you can just have the library notify your app when it has a valid token, when a new valid token has been obtained via refresh, or when the token cannot be refreshed (so the user needs to authenticate again).使用受人尊敬的客户端库来处理 OpenID Connect 详细信息,因此您可以让该库在具有有效令牌时、通过刷新获得新的有效令牌时或无法刷新令牌时通知您的应用程序(因此用户需要再次进行身份验证)。 The library should be configured (probably by default) to avoid storing the token at all.应该配置库(可能是默认设置)以避免存储令牌。

FAQ常问问题

What happens when someone refreshes the page?当有人刷新页面时会发生什么? I don't want to make them log in again.我不想让他们再次登录。

When the app first loads, it should always redirect the user to your Identity Provider.当应用程序首次加载时,它应该始终将用户重定向到您的身份提供者。 Based on how that identity provider handles things, there's a good chance the user won't have to log in. For example, if you're federating to an identity provider like Google or Microsoft, the user may have selected an option indicating that they are on a trusted device and they want to be remembered.根据身份提供者处理事情的方式,用户很可能不必登录。例如,如果您联合身份提供者(如 Google 或 Microsoft),用户可能已经选择了一个选项,表明他们在受信任的设备上,他们希望被记住。 If so, they won't need to log in again for a very long time, long after your auth token would have expired.如果是这样,他们在很长一段时间内都不需要再次登录,在您的身份验证令牌过期很久之后。 This is much more convenient for your users.这对您的用户来说更方便。

Then again, if the user indicated they're on a shared device and shouldn't automatically be logged in in the future, you want to force another login: you cannot differentiate between someone who refreshed their browser window and someone who reopened a closed browser and navigated to a page stored in the browser's history.再一次,如果用户表示他们在共享设备上并且以后不应该自动登录,你强制再次登录:你无法区分刷新浏览器 window 的人和重新打开关闭浏览器的人并导航到存储在浏览器历史记录中的页面。

Isn't the Identity Provider using cookies to keep the user logged in?身份提供者不是使用 cookies 来保持用户登录状态吗? What about CSRF or XSS attacks there?那里的 CSRF 或 XSS 攻击呢?

Those implementation details are specific to the Identity Provider.这些实现细节特定于身份提供者。 If they're using cookies, it's their job to implement Anti-CSRF measures.如果他们使用 cookies,那么他们的工作就是实施反 CSRF 措施。 They are far less likely than you are to use problematic third-party libraries, or import compromised external components, because their app only has one job .与您相比,他们使用有问题的第三方库或导入受损外部组件的可能性要小得多,因为他们的应用程序只有一项工作

Shouldn't I spend my time addressing XSS attacks instead?我不应该把时间花在解决 XSS 攻击上吗? Isn't it "game over" if someone injects code into my app?如果有人将代码注入我的应用程序,这不是“游戏结束”吗?

If it's an either/or proposition, and you have reason to believe your app has XSS or Code Injection vulnerabilities, then those should definitely take precedence.如果这是一个非此即彼的命题,并且您有理由相信您的应用程序存在 XSS 或代码注入漏洞,那么这些绝对应该优先考虑。 But good security involves following best-practices at multiple levels, for a kind of layered security.但良好的安全性涉及在多个级别遵循最佳实践,以实现一种分层安全性。

Plus, using a trusted third-party library to connect to trusted third-party security providers should hopefully save you time that you would have spent dealing with a variety of other security-related issues.此外,使用受信任的第三方库连接到受信任的第三方安全提供商应该有望为您节省处理其他各种安全相关问题的时间。

It is safe to store your token in localStorage as long as you encrypt it.只要您对其进行加密,就可以安全地将您的令牌存储在 localStorage 中。 Below is a compressed code snippet showing one of many ways you can do it.下面是一个压缩的代码片段,展示了您可以执行此操作的多种方法之一。

    import SimpleCrypto from 'simple-crypto-js';

    const saveToken = (token = '') => {
          const encryptInit = new SimpleCrypto('PRIVATE_KEY_STORED_IN_ENV_FILE');
          const encryptedToken = encryptInit.encrypt(token);

          localStorage.setItem('token', encryptedToken);
     }

Then, before using your token decrypt it using PRIVATE_KEY_STORED_IN_ENV_FILE然后,在使用您的令牌之前使用PRIVATE_KEY_STORED_IN_ENV_FILE解密它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将用户信息存储在localStorage中是否安全? - Is it safe to store the user information in localStorage? localstorage 注意更新 JWT Reactjs - localstorage do note update JWT Reactjs 如何在刷新页面上存储在本地存储中的 reactjs 中使用 JWT 进行身份验证? - How to authenticate using JWT in reactjs stored in localstorage on refresh page? 在会话/历史记录中存储用户数据是否安全?reactjs - is it safe to store users data in the session/history reactjs 2019 年我应该在哪里存储我的 JWT,localStorage 真的不安全吗? - Where should I store my JWT in 2019 and is the localStorage really not secure? 如何将我的 JWT 令牌存储在本地存储中? - How can I store my JWT Token in localstorage? ReactJS中的localStorage - localStorage in ReactJS LocalStorage JS - 刷新页面后存储数据以保持持久性是否安全? - LocalStorage JS - is it safe to store data to keep persistent after refreshing the page? 如何让子窗口数据存储在父窗口localstorage? (反应) - how to get child window data to store in parent window localstorage? (reactjs) 如何在 Angular 8 中存储像 jwt 令牌这样的数据? 是否有另一种使用本地存储或会话存储安全存储的方法? - How to store data like jwt token in Angular 8? Is there another way to store safely using localstorage or session storage?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM