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

时间:2018-07-02 20:25:15

标签: django security authentication cookies

因此,正如标题所述,我正在将Django Rest Framework与React结合使用。

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

我曾考虑过将令牌存储在cookie中,但这似乎并不十分安全。

还有其他类似问题,但没有答案能真正说明这有多少安全风险。我认为它很高,因为拥有令牌似乎足以验证后端的身份。

所以,我的问题是:我是否认为将身份验证令牌存储在cookie中是不安全的?

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

2 个答案:

答案 0 :(得分:5)

这也是我必须处理的事情。在此过程中失去了晚上的睡眠。

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

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

长版: 首先,让我们澄清一些事情。 React更像是一个移动应用程序,而不是网页/网站。我不是在谈论React Native-我的意思是React.js

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

在移动应用程序(或客户端独立应用程序)中,您需要维护某种令牌才能从本质上告诉服务器:“嘿,是我!我前一段时间来过。这是我的身份证。请允许我进入,请?”。问题是,很难在客户端确保令牌的安全。在Android v4.3之前,Android本身不提供任何安全的方式来存储身份验证令牌。这也不够安全,因此他们不久前引入了硬件支持的密钥库。这就是为什么某些应用无法(而且仍然无法)在有根设备上运行的原因。在此处详细了解:https://stackoverflow.com/a/19669719/3341737

与React /独立网络应用程序相比,Google(某种程度上)控制着Android客户端。对于他们来说,实现基于硬件的密钥库相对来说比较容易。如果是网络应用,则有成千上万的浏览器,其中包含数百种版本的浏览器。

回到window.localStorage。与Cookies相似,localStorage对每个域都是隔离的。由于它是更新的API,因此它的设计方式比旧的Cookie更好。

加密密钥没有意义(尽管您可能会对其进行混淆),因为您还需要将解密密钥存储在本地。因此,如果有人可以访问令牌,那么他们也可以访问解密密钥。

此问题的第二个方面(以及为什么“存储”不是唯一问题)是-您真正想保护令牌的人是谁?

  1. 男人在中间?使用SSL。
  2. 其他网站?他们无法访问您域的localStorage。
  3. 有人吗?真正。如果他们具有对计算机的物理访问权限,则可以轻松获得令牌。具有物理访问权限实际上使他们成为用户(您要保护令牌免受用户使用吗?)。考虑到该人具有物理访问权限,即使您以某种方式安全地存储它也不能保护该令牌。

为什么不呢?因为您需要随每个请求发送令牌-并且随每个请求发送的数据在浏览器网络检查器中可用。因此,无论您在何处以及如何存储令牌,都可以通过物理访问PC的人将其窃取。

为什么不使用Cookie?两个原因(实际上是1个):

  1. 默认情况下,Cookie随每个请求一起发送。您确实不需要这样做,因为您只需要在API调用期间发送令牌(而不是页面加载)即可。另外,由于您使用的是DRF(适用于任何RESTful API后端),您可能需要向服务器发送令牌是一种特定的方式-无论如何都需要自定义方法。
  2. window.localStorage是一个可以使用的简洁API(仅window.localStorage.setItem('key', 'value'))。而且,与Cookie相比,最大大小限制要高得多。

因此,window.localStorage在我看来是一个可行的选择。如果您有更好的解决方案,请告诉我。

话虽如此,这并不意味着您不能提高安全性。这里有一些建议:

  1. 在一定时间段或不活动一段时间后,从数据库中无效/删除令牌。
  2. 发送具有足够随机请求的更新令牌(也使前一个令牌无效),并用新令牌替换存储的令牌。
  3. 授予用户访问权以删除其帐户的已保存令牌以及每个令牌的上次活动。
  4. 如果您真的(真的)很关心,请将令牌与用户IP(或其他无法克隆到其他系统的东西)绑定。如果用户从新设备/位置/浏览器登录,请使用2FA。

答案 1 :(得分:0)

下一步是什么:不像在OAuth https://auth0.com/docs/tokens/refresh-token/current中那样存储令牌而是refresh_token吗?

您应该决定出于安全需要保留哪些超时,因此每次令牌失效或为空后,您都可以尝试使用存储在Cookie中的refresh_token还原会话

即使潜在的饼干在const超时后将获得refresh_token也没有道理