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", "*");