我目前正在使用ReactJS构建一个单页应用程序。
我读到不使用localStorage的原因之一是因为XSS漏洞。
既然React会转义所有用户输入,那么现在使用localStorage是否安全呢?
我目前正在使用ReactJS构建一个单页应用程序。
我读到不使用localStorage的原因之一是因为XSS漏洞。
既然React会转义所有用户输入,那么现在使用localStorage是否安全呢?
当前回答
看待这个问题的一种方法是考虑风险或伤害的水平。
你是否正在创造一款没有用户的应用,即POC/MVP?你是一家需要快速进入市场并测试应用程序的初创公司吗?如果是,我可能只会实施最简单的解决方案,并继续专注于寻找适合市场的产品。使用localStorage,因为它通常更容易实现。
你是在开发一款拥有大量日活跃用户的应用的v2版本,还是一款人们/企业非常依赖的应用?被黑客攻击是否意味着几乎没有恢复空间?如果是这样,我会仔细研究一下您的依赖关系,并考虑将令牌信息存储在仅http的cookie中。
使用localStorage和cookie/session存储都有各自的优缺点。
正如第一个答案所述:如果您的应用程序有XSS漏洞,那么两者都不能保护您的用户。由于大多数现代应用程序都有十几个或更多不同的依赖项,因此越来越难以保证应用程序的某个依赖项不受XSS攻击。
如果您的应用程序确实存在XSS漏洞,并且黑客已经能够利用它,那么黑客将能够代表您的用户执行操作。黑客可以通过从localStorage检索令牌来执行GET/POST请求,或者如果令牌存储在http-only cookie中,则可以执行POST请求。
在本地存储中存储令牌的唯一缺点是黑客将能够读取您的令牌。
其他回答
Localstorage被设计成可以通过javascript访问,所以它不提供任何XSS保护。正如在其他回答中提到的,有很多可能的方式来进行XSS攻击,默认情况下,本地存储不受保护。
However, cookies have security flags which protect from XSS and CSRF attacks. 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. 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. For example, sending an encrypted token in another cookie with some public user data.
因此,cookie是存储身份验证数据的更安全的选择。
localStorage和httpOnly cookie都不能接受吗?关于一个妥协的第三方库,我所知道的唯一能减少/防止敏感信息被窃取的解决方案是强制执行子资源完整性。
子资源完整性(SRI)是一种安全特性 浏览器验证它们获取的资源(例如从CDN) 交付时没有意外的操作。它通过允许 您可以提供所获取资源必须的加密散列 匹配。
只要受感染的第三方库在您的网站上是活跃的,键盘记录程序就可以开始收集信息,如用户名,密码,以及您输入到网站的任何其他内容。
httpOnly cookie将阻止来自另一台计算机的访问,但不会阻止黑客操纵用户的计算机。
TLDR;
两者都可以工作,但是使用httpOnly cookie要比使用localStorage安全得多,因为XSS引入的任何恶意javascript代码都可以读取localStorage。
基本上可以将JWT存储在localStorage中。
我认为这是一个好方法。 如果我们谈论的是XSS, XSS使用CDN,这也是一个潜在的风险,获得您客户的登录/通行证。将数据存储在本地至少可以防止CSRF攻击。
你需要了解这两点,然后选择你想要的。这两种攻击都不是你所需要注意的,只要记住:你的整个应用程序的安全性仅与你的应用程序的最不安全的点一样。
再次重申,存储是OK的,易受XSS, CSRF,…不是
我加入讨论的时间比较晚,但是由于OpenID Connect等更成熟和现代的认证协议的优势。
TL;DR:首选的方法是将JWT Token存储在内存中:而不是在cookie中,也不是在本地存储中。
细节
您希望将用户身份验证的责任与应用程序的其他工作分离开来。Auth很难得到正确的答案,少数几个花了所有时间思考这个问题的团队可能会担心你我永远都不会得到正确答案的细节。
为你的应用建立一个专用的身份提供者,并使用OpenID Connect协议进行身份验证。这可能是像谷歌、Microsoft或Okta这样的提供商,也可能是与一个或多个其他服务联合的轻量级身份服务器。
使用授权码流让用户验证并获得应用程序的访问令牌。使用一个受尊重的客户端库来处理OpenID连接细节,这样你就可以让库在应用程序拥有有效令牌、通过刷新获得新的有效令牌或当令牌无法刷新(因此用户需要再次验证)时通知应用程序。应该对库进行配置(可能是默认情况),以避免存储令牌。
FAQ
当有人刷新页面时会发生什么?我不想让他们再次登录。
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. 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.
同样,如果用户表示他们在共享设备上,将来不应该自动登录,那么您希望强制再次登录:您无法区分刷新浏览器窗口的用户和重新打开关闭的浏览器并导航到存储在浏览器历史记录中的页面的用户。
身份提供者不是使用cookie来保持用户登录吗?那么CSRF或XSS攻击呢?
这些实现细节是特定于身份提供程序的。如果他们使用cookie,他们的工作就是实施反csrf措施。他们比你更不可能使用有问题的第三方库,或者导入有问题的外部组件,因为他们的应用程序只有一个任务。
难道我不应该花时间解决XSS攻击吗?如果有人向我的应用程序中注入代码,这难道不是“游戏结束”吗?
如果这是一个非此即彼的命题,并且你有理由相信你的应用程序存在XSS或代码注入漏洞,那么这些肯定应该优先考虑。但是,对于一种分层的安全性来说,良好的安全性包括在多个级别上遵循最佳实践。
此外,使用受信任的第三方库连接到受信任的第三方安全提供者应该有望节省您处理各种其他安全相关问题的时间。