在 Django/DRF 中使用 JWT 身份验证并将 JWT 存储在 HttpOnly Cookie 中

Posted

技术标签:

【中文标题】在 Django/DRF 中使用 JWT 身份验证并将 JWT 存储在 HttpOnly Cookie 中【英文标题】:Using JWT authentication with Django/DRF and Storing JWTs in HttpOnly Cookies 【发布时间】:2021-06-18 08:42:48 【问题描述】:

我正在尝试在后端使用 Django 和 DRF 并在前端使用 ReactJs 构建一个 Web 应用程序,我想将它们分开(即避免服务器端渲染)。出于身份验证目的,我想使用 JWT我正在为此使用 djangorestframework-jwt。我在几个地方读过它,将 JWT 存储在本地存储中是不安全的,所以我试图为此使用 HttpOnly cookie。可以通过覆盖项目JWT_AUTH = 'JWT_AUTH_COOKIE': '<cookie name>', 的 settings.py 文件中的 drf-jwt 包的以下默认设置来配置 django 服务器发送 HttpOnly 来实现这一点,默认情况下设置为 none。服务器按预期发送 httpOnly cookie,但我面临一些问题:

1.同域约束

我知道 httpOnly cookie 不会附加到请求标头,除非请求是向托管在某个域上的服务器发出的。在我的情况下,我将 localhost:8000 用于 django,localhost:3000 用于我的 react 项目,因此浏览器不会附加 cookie,因为请求是针对不同的端口。我尝试同时在端口 3000 上运行这两个应用程序,并且浏览器确实在标头中附加了 cookie,并且我确实从服务器获得了 302 响应。然而,由于域冲突,它为各种问题打开了大门。我认为我可以使用 nginx 反向代理或类似的东西解决这个问题,但我不确定。请指导我如何在开发过程中在同一主机上同时提供这两个应用程序。

2。令牌刷新问题

当我参考视图设置来刷新令牌时,即使浏览器确实在请求标头中附加了 cookie,我也会遇到错误的请求错误。这是浏览器中的服务器响应

"token":["This field is required."]

感谢您一路阅读!

【问题讨论】:

【参考方案1】:

为了保证安全:

您需要CORS(快速入门:CORS_ALLOWED_HOSTS=["http://localhost:3000"], CORS_ALLOW_CREDENTIALS=True) 短期令牌(会话)cookie(5-15 分钟),应该有 HTTP-ONLY 设置 刷新令牌 cookie 具有 HTTP-ONLY 设置

那么你的基本流程是:

登录时 Django 创建会话令牌并发送它 您的 SPA 读取 cookie 并将其值添加到授权标头(授权:JWT ...token...) 对 Django 的任何请求都应该使用该 Authorization 标头

刷新流程为:

按照您使用的库的文档向刷新令牌端点发送请求 Django 然后读取 HTTP-ONLY cookie 并验证它 如果有效,Django 会发送一个新的刷新令牌作为 HTTP-ONLY cookie 以及一个新的短期令牌会话 cookie 刷新令牌过期后,您将用户注销。

article here 详细介绍了使用 GraphQL,但大部分前端代码的 cookie 部分和处理应该能够适应 REST。

【讨论】:

以上是关于在 Django/DRF 中使用 JWT 身份验证并将 JWT 存储在 HttpOnly Cookie 中的主要内容,如果未能解决你的问题,请参考以下文章

django drf框架中的user验证以及JWT拓展的介绍

django drf 自定义jwt用户验证逻辑

用于 Django3 + DRF 身份验证的 AWS Cognito

Django DRF序列化器或视图中的多表过滤

django drf JWT

Django - DRF自带的token认证和JWT区别