我会尝试一下这个复杂的主题。
什么是原产地?
源本身是主机的名称(方案、主机名和端口)ighttps://www.google.com
或者可以是本地打开的文件file://
等。它是某些东西(ig 网页)的来源。当您打开 Web 浏览器并转到 时https://www.google.com
,显示给您的网页的来源是https://www.google.com
。您可以在 Chrome Dev Tools 中看到Security
:
如果您通过文件资源管理器(不通过服务器提供)打开本地 HTML 文件,则同样适用:
这与CORS问题有什么关系?
当您打开浏览器并转到https://website.com
该网站时,该网站的来源将是https://website.com
. 该网站很可能只会获取图像、图标、js 文件并对 进行 API 调用https://website.com
,基本上它调用的是与提供服务的服务器相同的服务器。它正在调用同源。
例如,如果您打开 Web 浏览器并打开本地 HTML 文件,并且在该 html 文件中存在想要向 google 发出请求的 javascript,则会出现以下错误:
同源策略告诉浏览器阻止跨源请求。在这种情况下, originnull
正在尝试向https://www.google.com
(跨源请求)发出请求。由于设置了 CORS 策略,并且该策略是不允许跨域请求,因此浏览器将不允许这样做。
如果我的页面是从本地主机上的服务器提供的,则同样适用:
本地主机服务器示例
如果我们使用以下代码在 localhost:3000 上托管我们自己的 localhost API 服务器:
const express = require('express')
const app = express()
app.use(express.static('public'))
app.get('/hello', function (req, res) {
// res.header("Access-Control-Allow-Origin", "*");
res.send('Hello World');
})
app.listen(3000, () => {
console.log('alive');
})
并从文件资源管理器打开一个 HTML 文件(向 localhost:3000 服务器发出请求)目录,将发生以下错误:
由于网页不是从 localhost:3000 上的 localhost 服务器提供的,并且通过文件资源管理器,源与服务器 API 源不同,因此正在尝试跨源请求。由于 CORS 政策,浏览器正在停止此尝试。
但是如果我们取消注释注释行:
const express = require('express')
const app = express()
app.use(express.static('public'))
app.get('/hello', function (req, res) {
res.header("Access-Control-Allow-Origin", "*");
res.send('Hello World');
})
app.listen(3000, () => {
console.log('alive');
})
现在再试一次:
它有效,因为发送 HTTP 响应的服务器现在包含一个标头,说明跨域请求可以发生在服务器上,这意味着浏览器会允许它发生,因此没有错误。
如何解决问题(以下之一)
- 从与您发出的请求所在的位置(同一主机)相同的来源提供页面。
- 通过在响应标头中明确声明,允许服务器接收跨域请求。
- 如果使用反向代理(例如 NGINX),请配置 NGINX 以发送允许 CORS 的响应标头。
- 不要使用浏览器。例如,使用 cURL,它不像浏览器那样关心 CORS 策略,并且会得到你想要的。
示例流程
以下摘自:https : //web.dev/cross-origin-resource-sharing/#how-does-cors-work
请记住,同源策略告诉浏览器阻止跨源请求。当你想从不同的源获取公共资源时,资源提供服务器需要告诉浏览器“请求来自的这个源可以访问我的资源”。浏览器记住这一点并允许跨源资源共享。
步骤一:客户端(浏览器)请求当浏览器进行跨域请求时,浏览器会添加一个带有当前源(方案、主机和端口)的 Origin 标头。
第 2 步:服务器响应 在服务器端,当服务器看到这个标头,并希望允许访问时,它需要在响应中添加一个 Access-Control-Allow-Origin 标头,指定请求的来源(或 * 允许任何来源.)
第 3 步:浏览器接收响应 当浏览器看到带有适当 Access-Control-Allow-Origin 标头的响应时,浏览器允许与客户端站点共享响应数据。
更多链接
这是另一个很好的答案,更详细地说明了正在发生的事情:https : //stackoverflow.com/a/10636765/1137669