Access-Control-Allow-Origin 等于 origin 但浏览器仍然拒绝访问...为什么?

Access-Control-Allow-Origin equals origin but the browser still denies access... why?

我有一个应用程序 (React SPA) 在应用程序域的不同子域上调用一堆服务器,即:

当访问 api.foo.bar.com 时,我从浏览器(Edge、Chrome 或 Firefox)收到错误消息,告诉我来源 (foo.bar.com) 与Access-Control-Allow-Origin 响应的值 header。但是,通过检查响应,它们是相同的:

(不幸的是我不得不混淆地址。)

这些应用程序托管在 Kubernetes 上;入口是 NGINX,它不提供 CORS(cors-enabled 注释是错误的)。这两个应用程序(apimedia)都是 Express 应用程序,并且都具有相同的 CORS 配置,允许特定来源。

我想知道这是否与重定向有关 - 对 media... 端点的调用 returns 重定向 (302) 的位置是 api... 地址。

除此之外,我不知道还有什么问题。可以肯定的是,因为所有浏览器都同意我的请求应该被阻止(考虑到来源)。

在所有情况下,我都多次检查地址是否有拼写错误,以 forward-slashes 结尾等。我已经使用 cURL 和 Postman 在这些端点上调用 OPTIONS,使用所有 headers 或者只是几个。他们总是回答正确的地址。


其他信息,根据要求:

预检请求:

OPTIONS /media/1.0.0/rtsp/hls?feedUrl=https%3A%2F%2Flive.monuv.com.br%2Fa1%2F14298.stream%2Fstr27%2Fchunklist.m3u8%3Fm_hash%3DkhV_hCnKG3nhaNCFaYZxBnoMz-99idQVHiQh80ADW78%253D HTTP/2
Host: media.aiXXXXXXXXXXXXXX.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: GET
Access-Control-Request-Headers: feedurl
Referer: https://aiXXXXXXXXXXXXXXXX.com/
Origin: https://aiXXXXXXXXXXXXXXXX.com
DNT: 1
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Pragma: no-cache
Cache-Control: no-cache
TE: trailers

预检响应:

HTTP/2 204 No Content
date: Fri, 08 Oct 2021 13:33:10 GMT
x-powered-by: Express
access-control-allow-origin: https://aiXXXXXXXXXXXXXXXXXX.com
vary: Origin
access-control-allow-credentials: true
access-control-allow-methods: GET,HEAD,PUT,PATCH,POST,DELETE
access-control-allow-headers: Content-Type, feedUrl
strict-transport-security: max-age=15724800; includeSubDomains
X-Firefox-Spdy: h2

请求

预检通过,浏览器开始“飞行”请求:

GET /media/1.0.0/rtsp/hls?feedUrl=https%3A%2F%2Flive.monuv.com.br%2Fa1%2F14298.stream%2Fstr27%2Fchunklist.m3u8%3Fm_hash%3DkhV_hCnKG3nhaNCFaYZxBnoMz-99idQVHiQh80ADW78%253D HTTP/2
Host: media.aiXXXXXXXXXXXXXXXXXXXXX.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
feedUrl: https://live.monuv.com.br/a1/14298.stream/str27/chunklist.m3u8?m_hash=khV_hCnKG3nhaNCFaYZxBnoMz-99idQVHiQh80ADW78%3D
Origin: https://aiXXXXXXXXXXXXXXXX.com
DNT: 1
Connection: keep-alive
Referer: https://aiXXXXXXXXXXXXXXXXX.com/
Cookie: ory_kratos_session=MTYzMzYzODY1OHxEdi1CQkFFQ180SUFBUkFCRUFBQVJfLUNBQUVHYzNSeWFXNW5EQThBRFhObGMzTnBiXXXXXXXXXXXXYVc1bkRDSUFJSHBtUWxsaWFsVlJhWGRTVGxSMmIzZHRkbTFqYm5CUlRWVkdkelpPWkRoWnXXXTyqwgK-0Pe0qtZHjNhfU-YoASjg3istMZi672swQ==
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Pragma: no-cache
Cache-Control: no-cache
TE: trailers

回应

HTTP/2 302 Found
date: Fri, 08 Oct 2021 13:33:10 GMT
content-type: text/plain; charset=utf-8
content-length: 129
location: https://api.aiXXXXXXXXXXXXXXXXXX.com/media/1.0.0/hls/streams/19dd149d-f551-4093-b2aa-e5558388d545/hls.m3u8
x-powered-by: Express
access-control-allow-origin: https://aiXXXXXXXXXXXXXXXX.com
vary: Origin, Accept
access-control-allow-credentials: true
strict-transport-security: max-age=15724800; includeSubDomains
X-Firefox-Spdy: h2

在此响应中,浏览器未能指出 originaccess-control-allow-origin 不匹配。

(第一张图片来自Edge,日志比较清晰;此日志来自Firefox)

问题

来自浏览器的错误消息——我在下面使用虚拟 URL 和来源——可能有点令人困惑:

Access to XMLHttpRequest at 'https://api.example.com/' (redirected from 'https://media.example.com/') from origin 'https://example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'https://example.com' that is not equal to the supplied origin.

这里的关键是,正如 sideshowbarker 在 , because your first preflighted request to https://media.example.com/ responds with a cross-origin redirect to https://api.example.com/, the browser performs another whole CORS access-control check for that resource. However, because the redirect resulting from the first preflighted request happens to be cross-origin, the browser sets the origin of the second preflight request (which the error message refers to as the "supplied origin"), not as https://example.com, but !

中暗示的那样

以下是可能发生的事情的概要:

因为 https://api.example.com 可能不允许(也不应该!)允许 null,第二次访问控制检查失败,您会收到令人讨厌的 CORS 错误。

解决方案

抵制诱惑,让 null 起源于 https://api.example.com/,正如 doing so has serious security ramifications: it amount to voiding the protection that the Same-Origin Policy 所提供的那样。

相反,您应该摆脱从 https://media.example.com/https://api.example.com/ 的重定向,并让您的前端直接请求 https://api.example.com/ 资源。

或者,如果您不能完全摆脱重定向但可以更改其目的地,请将其设置为 同源 重定向(从某处 https://media.example.org 到其他地方https://media.example.org).