我目前正在使用ReactJS构建一个单页应用程序。

我读到不使用localStorage的原因之一是因为XSS漏洞。

既然React会转义所有用户输入,那么现在使用localStorage是否安全呢?


当前回答

只要加密,将令牌存储在localStorage中是安全的。下面是一个压缩的代码片段,展示了许多方法中的一种。

    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);
     }

然后,在使用令牌之前,使用PRIVATE_KEY_STORED_IN_ENV_FILE对其进行解密

其他回答

TLDR;

两者都可以工作,但是使用httpOnly cookie要比使用localStorage安全得多,因为XSS引入的任何恶意javascript代码都可以读取localStorage。

我对所有建议不要存储在本地存储的答案感到不安,因为这很容易受到XSS攻击或恶意库的攻击。其中一些问题甚至会进入冗长的讨论,尽管答案非常小/简单,我很快就会讲到。

这就相当于说:“不要用煎锅做饭,因为如果你某天晚上喝醉了,决定用煎锅做饭,你会把自己和房子都烤焦的。” 如果jwt由于XSS攻击或恶意库而泄露,那么站点所有者就有更大的问题:他们的站点容易受到XSS攻击或正在使用恶意库。

答案是:如果你确信你的网站不存在这些漏洞,那就去做吧。

裁判:https://auth0.com/docs/security/data-security/token-storage # browser-local-storage-scenarios

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是存储身份验证数据的更安全的选择。

如果你使用CDN是不安全的:

恶意JavaScript可以嵌入到页面中,Web存储就会受到威胁。这些类型的XSS攻击可以在不知情的情况下获取访问您站点的每个人的Web存储。这可能就是为什么许多组织建议不要在网络存储中存储任何有价值的东西或信任任何信息的原因。这包括会话标识符和令牌。 通过stormpath

您从外部需要的任何脚本都可能被破坏,并可能从客户机的存储中获取任何JWTS,并将个人数据发送回攻击者的服务器。

只要加密,将令牌存储在localStorage中是安全的。下面是一个压缩的代码片段,展示了许多方法中的一种。

    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);
     }

然后,在使用令牌之前,使用PRIVATE_KEY_STORED_IN_ENV_FILE对其进行解密