跨站点 cookie 的问题:如何将 cookie 从后端设置到前端
Posted
技术标签:
【中文标题】跨站点 cookie 的问题:如何将 cookie 从后端设置到前端【英文标题】:issue with cross-site cookies: how to set cookie from backend to frontend 【发布时间】:2020-11-10 14:23:07 【问题描述】:我目前正在开发我的第一个 web 应用程序,前端使用 React
,后端使用 FastAPI
。
我正在尝试与 Chrome 一起测试它——看看前端是否对后端进行了正确的 API 调用,并显示结果。我一直在使用 cookie 时遇到问题,我需要帮助。提前为这篇长文道歉——过去几天我浏览了很多资源,现在我不确定什么是相关的,什么不是。
localhost:8080
上的前端
http://127.0.0.1:8000
上的后端
使用以下FastAPI
后端代码正确设置 CORS(我相信):
app = FastAPI()
origins = [
"http://localhost:8080"
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
情况:前端向后端的http://127.0.0.1:8000/api/abc
发出GET
请求,后端设置了cookie。
/*===================== 尝试 1: 使用以下后端代码设置 cookie:
response.set_cookie(key="abcCookieKey", value="abcCookieValue")
并使用以下前端 JS 代码发出 GET
请求:
fetch('http://127.0.0.1:8000/api/abc',
method: 'GET',
credentials: 'include',
)
尝试 1 的结果:
在 Chrome 的 Console
标签上,我收到以下警告:
A cookie associated with a cross-site resource at http://127.0.0.1/ was set without the `SameSite` attribute. It has been blocked, as Chrome now only delivers cookies with cross-site requests if they are set with `SameSite=None` and `Secure`. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032.
在网络选项卡上,我在检查 set-cookie
响应标头时收到以下消息:
This Set-Cookie was blocked because it has the "SameSite=Lax" attribute but came from a cross-site response which was not the response to a top-level navigation.
====================*/
...所以我做了一些研究,然后想出了
/*===================== 尝试 2: 使用以下后端代码设置 cookie:
response.set_cookie(key="abcCookieKey", value="abcCookieValue", samesite="none", secure=True)
并使用相同的前端 JS 代码发出 GET
请求。
尝试 2 的结果:
在 Chrome 的 Console
选项卡上,我收到与尝试 1 完全相同的警告,即使响应标头具有 set-cookie
和 Samesite=none; Secure
。此外,标题有以下警告
This Set-Cookie was blocked because it had the "Secure" attribute but was not received over a secure connection.
====================*/
..所以我尝试使用https
并提出:
/*=====================
尝试 3:
一切都与尝试 #2 相同,除了在我的 JS 获取代码中,我使用 fetch('https://127.0.0.1:8000/api/abc ...
然后我在使用uvicorn
运行的后端收到以下警告:WARNING: Invalid HTTP request received.
====================*/
问题:
-
尝试#2 是否遗漏了什么?肯定有一种简单的方法来设置从后端到前端的 cookie,而不用担心 https?
如果我别无选择,只能使用
https
,如何在本地运行可以使用https
访问的后端服务器?我所做的研究使它看起来像是一个复杂/耗时的过程。 (但是,公平地说,我对 web-dev/all things network 的理解非常有限)。
【问题讨论】:
你解决了吗? 简短的回答是否定的,我没有解决它。我刚结束使用 Safari 来解决它,然后在部署后检查它是否可以在 Chrome 上运行。 你是怎么解决沙山的? 请发布答案@ShashanSooriyahetti,因为您可以看到我们很多人都想知道。 @Marisha 我已经添加了答案,因为你们要求随时问 anthing 【参考方案1】:您可以通过转到“chrome://flags”并禁用“没有 SameSite 的 Cookie 必须是安全的”来完全禁用此功能。但是,这将对所有网站禁用它,因此当您不进行开发时,它的安全性会降低。
【讨论】:
这不起作用,我仍然收到“安全”错误【参考方案2】:我会尝试给出这个概念。
首先请知道我使用的是从SailsJS
开发的后端和从AngularJS
开发的前端以及连接到使用Angular9
开发的后端的应用程序。
我正在为前端(CMS)使用仅限 http 的 cookie,以授予向已登录用户添加内容的权限。身份验证成功后,将为他们设置仅限 HTTP 的 cookie。
请注意,http cookie 有一个棘手的部分,并且后端和前端都提供不同的 URL,就像在呈现的场景中一样。
积分:
因此,在开发过程中,您必须将后端和前端托管在同一 IP 下。 前任。我的后端:192.168.8.160:1337,前端:192.168.8.160:81。 不同的端口相同的ip。
这不是投入生产时的场景,您可以拥有任何域:)
您必须在后端允许 CORS 并让您的前端 ip:port 在接受的来源下。
实施,你必须确定你的环境,在我的情况下,
if (sails.config.environment === 'development')
res.setHeader('Set-Cookie',[`token=$token; Path=/;HttpOnly; maxAge=86400000;SameSite=false;`]);
else
res.setHeader('Set-Cookie',[`token=$token; Path=/;HttpOnly; maxAge=86400000;SameSite=None;Secure=true;`]);
请注意,在上面的开发环境代码中,您需要SameSite=false
,因此您需要具有相同的ip,因为我们不能拥有SameSite=None
,因为它需要Secure=true
,然后需要HTTPS。在开发模式下实现会很头疼。
就是这样,伙计们。如果你做对了,你就可以做到这一点。
【讨论】:
非常感谢...这个答案。节省了我的大量时间。我使用 Django + React(JWT Auth.)。当我在后端设置 Httponly cookie 但未在前端 api 请求中设置时。 我一整天都在尝试解决完全相同的问题。这个答案为我做了。我仍然不明白 samesite false 和 same samesite none 之间有什么区别。我以为我他们是完全相同的东西。无论如何,现在就可以了 如果您正在使用 create react app 并想使用 HTTPS,只需将 HTTPS=true 添加到 package.json 中的启动脚本: scripts: "start": "HTTPS=true react-scripts start " @Rem 不错,angular还支持带有ng s --ssl的HTTPS @hainabaraka,您应该立即将其标记为已接受的答案,这是一个真正出色的解释【参考方案3】:删除通配符,因为allow_credentials=True
不允许使用通配符:
app.add_middleware(
CORSMiddleware,
allow_origins=['http://localhost:8080'],
allow_credentials=True,
allow_methods=["GET", "POST", "OPTIONS"], /* include additional methods as per the application demand */
allow_headers=["Content-Type","Set-Cookie"], /* include additional headers as per the application demand */
)
在设置 cookie 时将 samesite
设置为 none
(现代浏览器需要它):
/* `secure=True` is optional and used for secure https connections */
response.set_cookie(key='token_name', value='token_value', httponly=True, secure=True, samesite='none')
如果客户端使用 Safari,请禁用 Preferences
中的 Prevent cros-site tracking
。就是这样!
【讨论】:
以上是关于跨站点 cookie 的问题:如何将 cookie 从后端设置到前端的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring Boot 中设置同站点 cookie 标志?
Set-cookie 不适用于 Dot net Core 3.1 中的跨站点请求/响应和 React 设置同站点 cookie 和/或 CORS 问题