如何存储 JWT refreshToken cookie 响应

Posted

技术标签:

【中文标题】如何存储 JWT refreshToken cookie 响应【英文标题】:How to store a JWT refreshToken cookie response 【发布时间】:2021-11-16 20:46:00 【问题描述】:

我正在尝试使用 GraphQL 通过 JWT 对用户进行身份验证。登录用户后,我会收到作为 JSON 响应的令牌和存储刷新令牌的 httponly cookie。 (服务端使用的是 Saleor-core)

根据 Saleor 的文档和其他一些博客文章,我假设这个响应 cookie 现在应该存储在浏览器中,并且每当我需要刷新令牌时,cookie-refreshToken 用于验证我的请求。但是,当我在开发工具中将选项卡切换到“应用程序”时,它只是空的。

浏览器收到 cookie 响应后的正常行为是什么?我是否需要一些额外的代码来以某种方式“保存”该响应 cookie?

并没有真正发现其他人有这个问题,所以我认为错误一定是在其他地方。

更新

我在某处读到问题可能是由于服务器调试模式没有“安全”标志。我把它关掉了,但仍然没有设置 cookie。

响应标头:

HTTP/1.1 200 OK
Connection: keep-alive
Date: Thu, 23 Sep 2021 13:32:33 GMT
Server: uvicorn
Content-Type: application/json
Access-Control-Allow-Origin: https://rewhite-86006--beta-duoa0dwg.web.app
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization, Authorization-Bearer
Access-Control-Allow-Credentials: true
Content-Length: 912
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Set-Cookie: refreshToken=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MzI0MDM5NTQsIm93bmVyIjoic2FsZW9yIiwiZXhwIjoxNjM0OTk1OTU0LCJ0b2tlbiI6Ijd2b0VmMm1DNlZZSyIsImVtYWlsIjoiSnVsaWFuLkZpbmtlQGdtYWlsLmNvbSIsInR5cGUiOiJyZWZyZXNoIiwidXNlcl9pZCI6IlZYTmxjam8zTmc9PSIsImlzX3N0YWZmIjpmYWxzZSwiY3NyZlRva2VuIjoiWm55ek9xVG9rOU9GYXlDZXY0cjFxMUxnaktnTXRRR0VNUVJEalR1eTJDZ1IyOW1GSVBxQ1B1T1hZcTFQNk92cyJ9.Cl6PmoLkO9Hlh36tDOuyNLQCib4FVBwn32hhnmd7Q4E; expires=Sat, 23 Oct 2021 13:32:34 GMT; HttpOnly; Max-Age=2592000; Path=/; Secure
Via: 1.1 vegur

请求标头:

POST /graphql/ HTTP/1.1
Host: rewhite-saleor-engine.herokuapp.com
Connection: keep-alive
Content-Length: 318
Pragma: no-cache
Cache-Control: no-cache
sec-ch-ua: "Google Chrome";v="93", " Not;A Brand";v="99", "Chromium";v="93"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/93.0.4577.82 Safari/537.36
sec-ch-ua-platform: "macOS"
content-type: application/json
Accept: */*
Origin: https://rewhite-86006--beta-duoa0dwg.web.app
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://rewhite-86006--beta-duoa0dwg.web.app/
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7

感谢您的帮助!

【问题讨论】:

我注意到您的响应 Cookie 的 Domain 属性与您在应用程序 Cookie 中的属性不同。可能值得导航到浏览器中 cookie 提供的域 url,并检查 cookie 是否可用。 @Mythos 谢谢,这是一个很好的提示。不幸的是,那里也没有 cookie。也许只是因为域不同而没有保存? 是的,我就是这么想的,我只是想核对一下,以防我错了。介意我将其添加为答案吗? 【参考方案1】:

您 cookie 上的 Domain 属性似乎与您的请求来源不同。您正在发出跨站点请求并从(不同域的)服务器接收 Set Cookie 响应。

通常我们在不同域(例如localhost:3000localhost:8080)上运行后端和前端时会遇到这个问题。

解决方案:

    如果 cookie 设置了 SameSite=NoneSecure 属性,则最近的 Chrome 浏览器版本(从 2020 年开始)将仅设置从跨站点请求接收的 cookie。设置Secure 后,cookie 将仅通过 HTTPS 协议发送到服务器(您需要实现 SSL)。 截至目前,您也没有设置。 SameSite 默认为 Lax 而不是 None。您需要明确设置它。

    您需要实现一个代理,以便您在 https://rewhite-86006--beta-duoa0dwg.web.app 上请求您的 webapp,您的 webapp 会将其代理到您的 Saleor 引擎域 rewhite-saleor-engine.herokuapp.com。你如何做到这一点取决于你使用什么框架来为你的 webapp 提供服务。您没有在问题中提到它,但我注意到您已将其标记为 vue.js,因此我假设您使用 Vue CLI 来提供 Vue 应用程序。

使用 Vue CLI 设置代理非常简单。只需在根目录中查找 vue.config.js 文件即可。如果它不存在,请创建它并粘贴以下代码:

module.exports = 
    devServer: 
        proxy: 
            '^/graphql': 
                target: 'https://rewhite-saleor-engine.herokuapp.com',
                changeOrigin: true,
                logLevel: 'debug',
            ,
        ,
    ,

现在,您应该将请求发送到https://rewhite-86006--beta-duoa0dwg.web.app/graphql,而不是从rewhite-saleor-engine.herokuapp.com/graphql 获取refreshToken,您的Web 应用本地服务器会将请求转发到Heroku 上的Saleor 后端。对于您的浏览器,它看起来好像请求的响应来自 web 应用程序本身,因此它不再是跨站点请求。

【讨论】:

谢谢,我现在运行了几个测试,不幸的是没有一个成功。我现在得到了安全标志,实现了 SSL,我什至正在运行从 mydomain.com 到 saleorengine.mydomain.com 的请求。但是,SameSite 是空的 - 我想这只能在服务器端设置?还是从后端开发的角度不设置这个值背后有什么逻辑? Saleor 在demo.saleor.io 有一个演示商店,如果您单击菜单中的帐户图标并使用示例凭据登录,则会设置 refreshCookie(即使 SameSite 也是空的)。 是的,通常服务器会发送带有 Set-Cookie 标头的响应,所有 cookie 选项都在此标头中定义,然后 Chrome 决定设置它。设置 cookie 后,您可以在浏览器中修改这些选项,但在您的情况下,它根本没有设置。 demo.saleor.io 有效,因为它没有发出跨站点请求。请注意,该 cookie 中的 Domain 属性与 URL 相同。 如果服务器不在您的控制范围内,那么我建议您尝试我的第二种解决方案。在你的 webapp 中实现一个代理。因此,从浏览器的角度来看,它不是跨站点请求,因为它被发送到您的 webapp 前端服务器 (https://rewhite-86006--beta-duoa0dwg.web.app),Chrome 很乐意设置您的 cookie。 我在 Heroku 服务器上运行 Saleor Core,因为它是开源的(目前处于测试阶段)。可能是一个错误 - 但我应该在服务器端注意什么来修复它?我认为可以在此处找到该功能:“create_refresh_token”中的 saleor/core/jwt.py

以上是关于如何存储 JWT refreshToken cookie 响应的主要内容,如果未能解决你的问题,请参考以下文章

公开refreshtoken API是不是安全

如何使用 Angular Http Interceptor 和 RxJS 刷新 JWT 令牌?

将 JWT RefreshToken 作为 Set-Cookie 发送

如何使用 JWT 刷新令牌生成新的访问令牌

使用拦截器获取refreshtoken后如何调用相同的请求?

jwt 访问令牌和刷新令牌流