在cookie中保存身份验证令牌(Django Rest Framework+;React)

在cookie中保存身份验证令牌(Django Rest Framework+;React),django,security,authentication,cookies,Django,Security,Authentication,Cookies,因此,正如标题所说,我正在使用Django Rest框架,并结合React 我使用令牌身份验证对用户进行身份验证。现在我面临一个问题。当我重新加载页面时(例如,按F5键),所有状态都消失了,在这种情况下,我无法保存令牌,需要用户再次登录 我想把代币储存在一块饼干里,但那似乎不太安全 还有其他类似的问题,但没有任何答案能够真正解释这有多大的安全风险。我认为这是相当高的,因为拥有令牌似乎足以作为后端的某人进行身份验证 所以,我的问题是:我认为在cookie中存储身份验证令牌不安全的假设是真的吗 注意

因此,正如标题所说,我正在使用Django Rest框架,并结合React

我使用令牌身份验证对用户进行身份验证。现在我面临一个问题。当我重新加载页面时(例如,按F5键),所有状态都消失了,在这种情况下,我无法保存令牌,需要用户再次登录

我想把代币储存在一块饼干里,但那似乎不太安全

还有其他类似的问题,但没有任何答案能够真正解释这有多大的安全风险。我认为这是相当高的,因为拥有令牌似乎足以作为后端的某人进行身份验证

所以,我的问题是:我认为在cookie中存储身份验证令牌不安全的假设是真的吗


注意:我正在考虑切换到基于会话的身份验证,但我宁愿确保我的工作安全并保留令牌身份验证。

我忘记了我的旧答案仍然在互联网上获得一些牵引力。。。正如我后来意识到的那样,这部分是错误的。

最新答复:
我曾考虑将令牌存储在cookie中,但这似乎不太安全。

如果操作正确,就足够安全了。是的,具有系统物理访问权限的任何人仍然可以读取cookie。下面将对此进行详细介绍

让我们明确一点,在客户端(本例中为浏览器)存储一些数据并通过API调用发送这些数据以验证用户身份是绝对必要的。让我们将此数据称为“令牌”

当您在API调用中发送此令牌时,任何具有系统物理访问权限的人都可以查看它。而且,加密也没有意义,因为

  • 您需要在发送之前对其进行解密,这将使未加密的字符串可读
  • 您还需要将解密密钥存储在客户端,这将使我们回到同样的问题
  • 有哪些选择?老实说,随它去吧。大多数网站都是这样工作的(几乎是这样)。除非网站上有一些非常敏感的信息。在这种情况下,看看基于时间的密码,基于硬件的密码,也许是生物指标?这些方法大多将安全保管钥匙的责任转交给用户

    当然,你可以让它更安全。以下是一些提示:

  • 在特定时间段/不活动后从服务器中删除令牌
  • 在随机请求上更新令牌,并使以前的请求无效
  • 允许用户查看并删除活动会话
  • 将其绑定到用户IP或难以复制的内容。每次用户使用不同的IP登录时,请输入密码
  • 考虑到这一点,我们来讨论存储令牌

    我们只需要确保其他网站、恶意脚本和软件无法访问存储的令牌。(如上所述,用户始终可以读取令牌。)

    您可以将其存储在
    cookies
    localStorage
    中。两者都可以正常工作,但是
    localStore
    设计用于存储更大的数据
    Cookies
    最多可以存储4096字节的数据,这足以存储令牌<代码>Cookies在处理SSR(服务器端渲染)时也会有所帮助。不过,在React中处理cookies可能会变得很棘手。(提示:试试next.js,它内置了对Cookie和带有React的SSR的支持。)

    如果有帮助,您还可以在cookies中指定过期时间

    TL;DR:使用
    Cookies
    非常好。只要使用得当

    感谢@ShayanSalehian指出:
    LocalStorage受XSS约束,cookie受CSRF约束。因此,我认为使用cookies+CSRF是最安全的方式,即使是在令牌身份验证中,在客户端存储令牌…


    旧答案(剧透警报,部分错误): 这也是我必须处理的事情。在这个过程中失去了几个晚上的睡眠

    免责声明:我不是任何安全专家。只是有点痴迷(阅读:偏执狂)

    简短版本(回答您的问题):我最终使用window.localStorage来存储令牌。虽然我不相信这是最好的做法,但这不仅仅是“存储”部分阅读的长版本,以了解更多

    长版本: 首先,让我们澄清一些事情。React更像一个移动应用程序,而不是一个网页/网站。我不是在说你的母语-我是说

    为什么我说它更像一个移动应用程序而不是一个网站? 传统网站通常使用基于会话的身份验证,浏览器/服务器通常为此做好准备。显然,这是一项毫不费力、无缝的任务

    在移动应用程序(或客户端独立应用程序)中,您需要维护某种令牌来告诉服务器“嘿,是我!我刚才访问过。这是我的身份证。请让我进去?”。问题是,在客户端很难保证令牌的安全。在Android v4.3之前,Android本身没有提供任何安全的方式来存储身份验证令牌。这也不够安全,所以他们在不久前引入了硬件支持的密钥库。这就是为什么一些应用程序不能(现在仍然不能)与根设备一起工作的原因。请在此处阅读更多信息:

    与React/独立web应用程序相比,谷歌(在某种程度上)控制着Android客户端。对他们来说,实现基于硬件的密钥库相对比较容易。就web应用而言,有很多浏览器,有数百个版本等等

    回到window.localStorage。与Cookie类似,localStorage对每个域都是隔离的。因为它是一个较新的API,所以它的设计方式比好的旧Cookie要好

    加密密钥没有意义(尽管您可能会混淆它),因为您还需要将解密密钥存储在本地的某个位置。因此,如果有人可以访问令牌,他们也可以访问解密密钥

    这个问题的第二个方面(和w