Access-Control-Allow-Origin 头部如何工作?


在本教程中,我们将学习访问控制如何允许源标头工作。

Access-Control-Allow-Origin 是 CORS 的一个头部。使用 CORS 或跨源资源共享,浏览器可以允许托管在源 A 上的网站请求源 B 上的资源。

源是端口、主机名和方案的混合,例如 http://tutorialspoint.example.com:5000/,而不仅仅是主机名。

以下是如何将其付诸实践的示例 -

  • 我想从源 B(即 http://yoursite.com)和源 A:https://tutorialspoint.com 获取资源。

  • 浏览器将拒绝我的请求并阻止我访问 yoursite.com 的资源以维护您的安全。

  • 您的源 B 必须通知浏览器允许源 A 访问您的资源,以接受我从您的源接收资源。

浏览器允许源共享资源是由于 CORS。

源之间资源共享的关键标头是 Access-Control-Allow-Origin,尽管还有其他一些标头。浏览器通过这些标头被告知哪些源被允许向此服务器发送请求。

谁需要配置 Access-Control-Allow-Origin?

请考虑以下示例以确定谁应该设置此标头:您正在查看一个可以查看和收听歌曲的网站。该网站在后台偷偷尝试连接到您的银行。

因此,银行必须将 Access-Control-Allow-Origin 标头设置为响应的一部分,以保护其资源。请记住,此标头必须由负责提供资源的源设置。

什么是 CORS?

CORS 或跨源资源共享是一种方法,它通过使用额外的 HTTP 标头告诉浏览器可以使用其他源。

用于访问 URL 的协议、主机和端口标识 Web 内容片段的源。如果两个项目的方案、主机和端口相同,则它们可以共享相同的源。

当告诉浏览器接受来自任何源的代码以访问资源时,响应应为 -

Access-Control-Allow-Origin: *

非简单请求

事件的网络级别可能比之前描述的稍微复杂一些。为了确定服务器是否会接受“非简单”请求,浏览器首先发出一个无数据的“预检”OPTIONS 请求。当以下任一(或两者)情况发生时,请求不是简单的

  • 使用 GET 或 POST 之外的 HTTP 动词(例如,PUT、DELETE)

  • 使用复杂的请求标头(唯一的特定请求标头是 -

Accept、Accept-Language、Content-Language 和 Content-Type(只有当值为 text/plain、application/x-www-form-url 编码或 multipart/form-data 时,这才简单)。如果服务器使用与非简单动词和非简单标头匹配的响应标头(对于非简单标头使用 Access-Control-Allow-Headers,对于非简单动词使用 Access-Control-Allow-Methods)来响应 OPTIONS 预检,则浏览器将发送请求。如果站点 A 想要发送对 /somePage 的 PUT 请求,并且 Content-Type 值为非简单的 application/json,则浏览器将首先执行预检请求 -

OPTIONS /somePage HTTP/1.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

需要注意的是,浏览器会自动添加 Access-Control-Request-Method 和 Access-Control-Request-Headers;您无需添加这些。例如,此 OPTIONS 预检的成功响应标头如下 -

Access-Control-Allow-Origin: http://siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type

发送提案时的行为与处理简单请求的方式相同(一旦预检完成)。换句话说,如果非简单请求的预检成功,则它将被视为简单请求(即,服务器仍然必须再次发送 Access-Control-Allow-Origin 以进行实际响应)。

The browsers send the actual request:
PUT /somePage HTTP/1.1
Origin: http://siteA.com
Content-Type: application/json
{ "myRequestContent": "JSON is so great" }

并且与简单请求完全一样,服务器会回复 Access-Control-Allow-Origin -

Access-Control-Allow-Origin: http://siteA.com

示例

在下面的示例中,我们创建了一个在 localhost 的端口 5000 上运行的服务器。在此应用程序中,我们将 Access-Control-Allow-Origin 标头设置为 tutorialspoint。如果我们从 tutorialspoint 与服务器通信,则它将正常工作。但是,如果我们尝试与任何其他域通信,它将抛出错误。我们无法从除 tutorialspoint.com 之外的其他域发送任何 get 或 post 请求。

const express = require("express");
const app = express();
// Access-Control-Allow-Origin
app.use((req, res, next) => {
   res.setHeader("Access-Control-Allow-Origin", "https://tutorialspoint.com");
   res.header(
      "Access-Control-Allow-Headers",
      "Origin, X-Requested-With, Content-Type, Accept"
   );
   next();
});
app.get("/view", (req, res) => {
   res.send("Welcome to Tutorialspoint!");
});
app.listen(5000, () => console.log('Listening on port 5000'));

尝试从 localhost:3000/ 向 localhost:5000/ 发送 get 请求。

fetch('https://127.0.0.1:5000/view')
.then(response => console.log(response));

输出


将标头更改为以下内容以解决此问题 -

res.setHeader("Access-Control-Allow-Origin", "*");

更新于: 2022-12-06

3K+ 浏览量

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告