我在扯头发.请帮忙!我有一个用户界面SPA应用程序,它是身份应用程序的前端.该应用程序具有一个登录API,用于设置身份验证cookie.SPA使用具有credentials: "same-origin"fetch函数将登录凭据发布到此登录API端点,因为它期望包含会话cookie的响应上有Set-Cookie头.然后,它将浏览器重定向到与API位于同一域上的回调端点,该API需要请求中的会话cookie.

当我在本地运行此操作时,它会按预期工作,以下是跟踪:

  1. 登录API请求:
POST https://identity.mywebsite.local:44119/auth/email HTTP/1.1
Host: identity.mywebsite.local:44119
Connection: keep-alive
Content-Length: 39
sec-ch-ua: "Microsoft Edge";v="123", "Not:A-Brand";v="8", "Chromium";v="123"
sec-ch-ua-platform: "Windows"
DNT: 1
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0
Content-Type: application/x-www-form-urlencoded
Accept: */*
Origin: http://my.mywebsite.local:3100
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://my.mywebsite.local:3100/
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-GB,en;q=0.9

email=test@test.com&password=mypassword
  1. 登录API响应(注意正在设置的mywebsite-identity cookie):
HTTP/1.1 200 OK
Content-Length: 0
Date: Fri, 26 Apr 2024 11:00:50 GMT
Server: Kestrel
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://my.mywebsite.local:3100
Cache-Control: no-cache,no-store
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache
Set-Cookie: mywebsite-session=1F13A118FA46BD80ED830D1AFEBDAA0D; path=/; secure; samesite=none
Set-Cookie: mywebsite-identity=[value]; expires=Fri, 10 May 2024 11:00:51 GMT; path=/; secure; samesite=none; httponly
R-Source: identity
  1. 回调请求(注意发送的mywebsite-identity cookie):
GET https://identity.mywebsite.local:44119/connect/authorize/callback?client_id=www&... HTTP/1.1
Host: identity.mywebsite.local:44119
Connection: keep-alive
sec-ch-ua: "Microsoft Edge";v="123", "Not:A-Brand";v="8", "Chromium";v="123"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
DNT: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://my.mywebsite.local:3100/
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-GB,en;q=0.9
Cookie: mywebsite-session=1F13A118FA46BD80ED830D1AFEBDAA0D; mywebsite-identity=[value]

但当我将此确切的代码部署到远程环境时,浏览器不再设置API响应中接收的cookie.这是踪迹:

  1. 登录API请求:
POST https://identity-build.mywebsite.org.uk/auth/email HTTP/1.1
Host: identity-build.mywebsite.org.uk
Connection: keep-alive
Content-Length: 50
sec-ch-ua: "Microsoft Edge";v="123", "Not:A-Brand";v="8", "Chromium";v="123"
sec-ch-ua-platform: "Android"
DNT: 1
sec-ch-ua-mobile: ?1
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Mobile Safari/537.36 Edg/123.0.0.0
Content-Type: application/x-www-form-urlencoded
Accept: */*
Origin: https://my-build.mywebsite.org.uk
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://my-build.mywebsite.org.uk/
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-GB,en;q=0.9

email=test@test.com&password=mypassword1
  1. 登录API响应(请注意mywebsite-identity cookie已按预期设置):
HTTP/1.1 200 OK
Date: Fri, 26 Apr 2024 11:03:00 GMT
Content-Length: 0
Connection: keep-alive
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://my-build.mywebsite.org.uk
Cache-Control: no-cache,no-store
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache
Set-Cookie: mywebsite-session=1C5F6777E03D96BD215029199901B927; path=/; samesite=none
Set-Cookie: mywebsite-identity=[value]; expires=Fri, 10 May 2024 11:03:00 GMT; path=/; samesite=none; httponly
Request-Context: appId=cid-v1:fff610af-e464-4fb4-8ece-c73f6587e07b
R-Source: identity
CF-Cache-Status: DYNAMIC
Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=WHaIgYERtzjcCm5robKrgl0nLh0XZSHWmaPoU48%2B5MTDDWgVXSs9MO%2Fqe2q4lgutPrR6HdSEAfFbNlh42Xmzw0AEU2TqIlEbynCNJVt4Qkd7VZ3TxVLfM2kjxut6br84jgUmYR2C9HjFj0RaG5"}],"group":"cf-nel","max_age":604800}
NEL: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
Server: cloudflare
CF-RAY: 87a6156f2b3071e1-LHR
alt-svc: h3=":443"; ma=86400
  1. 回调请求(notice no cookies are sent because the browser didn't set them from the previous response):
GET https://identity-build.mywebsite.org.uk/connect/authorize/callback?client_id=www&... HTTP/1.1
Host: identity-build.mywebsite.org.uk
Connection: keep-alive
Upgrade-Insecure-Requests: 1
DNT: 1
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Mobile Safari/537.36 Edg/123.0.0.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
sec-ch-ua: "Microsoft Edge";v="123", "Not:A-Brand";v="8", "Chromium";v="123"
sec-ch-ua-mobile: ?1
sec-ch-ua-platform: "Android"
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-GB,en;q=0.9

我看不出有什么不同而产生这种影响.

如果有用的话,SPA是一个nextjs应用程序(其中API调用是客户端),获取代码就这样简单:

fetch(url, {
  method: "POST",
  credentials: "same-origin",
  headers:{
    'Content-Type': 'application/x-www-form-urlencoded'
  },    
  body: formData
})

我应该指出的是,尽管API在identity-build.mywebsite.org.uk上运行(这也是我希望设置cookie的域),但调用它的SPA在my-build.mywebsite.org.uk上运行.我的假设是,我们在这里担心的起源(就浏览器cookie安全性而言)是API的域.

推荐答案

在您的开发配置中,secure标志在Set-Cookie个响应标头中发送,而在构建配置中,不包括secure标志.在开发和构建格式中,Set-Cookie个标题都包括samesite=none标志.如果设置了samesite=none,则必须包括secure标志,否则cookie将被阻止.见Set-Cookie on MDN Docs.

要解决此问题,请确保您使用有效的HTTPS配置并编辑响应标头以确保Set-Cookie包含secure标志.

或者,由于这些网站是同一域的子域名,因此该请求不被视为跨源请求,因此无需包括samesite=none标志即可在请求中发送cookie.删除samesite=none标志可以解决问题并降低CSRF的风险.

奇怪的是,API在dev中发送有效的Set-Cookie标头,但在构建中却没有.如果您控制API,则可以按照上述步骤解决问题.如果您不控制API,则应首先判断您的HTTPS配置是否有效,然后联系开发人员.

Javascript相关问答推荐

如何使用CSS和JavaScript创建粘性、凝聚力的形状到形状(容器)变形?

在JavaScript中打开和关闭弹出窗口

Next.js Next/Image图像隐含性有任何类型-如何修复?

ReactJS中的material UI自动完成类别

useNavigation更改URL,但不呈现或显示组件

Exceljs:我们在file.xlsx(...)&#中发现了一个问题'"" 39人;

在react JS中映射数组对象的嵌套数据

我正在建立一个基于文本的游戏在react ,我是从JS转换.我怎样才能使变量变呢?

如何修复我的数据表,以使stateSave正常工作?

在运行时使用Next JS App Router在服务器组件中运行自定义函数

从Nextjs中的 Select 项收集值,但当单击以处理时,未发生任何情况

检索相加到点的子项

为什么在函数中添加粒子的速率大于删除粒子的速率?

Next.js中的服务器端组件列表筛选

删除元素属性或样式属性的首选方法

是否可以将异步调用与useState(UnctionName)一起使用

在JavaScript中将Base64转换为JSON

调用特定数组索引时,为什么类型脚本不判断未定义

计算对象数组中属性的滚动增量

Played link-Initialize.js永远显示加载符号