1. CORS 产生的原因
CORS 全称为(Cross-Origin Resource Sharing:跨站资源共享),跨域请求是由于浏览器的同源策略(Same-Origin Policy)引起的,那么 CORS 的产生和浏览器的同源策略有关系,我们先了解什么是同源策略。
2. 什么是同源策略
SOP 是所有的现代浏览器都具备的安全措施,它不允许从一个加载的js脚本和资源的 Origin 域与另一个 Origin 域进行交互。换句话说,如果您的网站是 www.a.com
,则您无法向 www.b.com
发出XHR请求。
如果说 SOP 是限制跨源访问的一种方式,那么 CORS 则是一种绕过 SOP 限制并允许您的前端向服务器提出合法请求的方法。
3. 什么是 Origin
Origin 翻译为源(域),在 CORS 上下文中 Origin 由三个元素组成:
Origin = 协议 + 域名 + 端口
协议(Protocol) :例如,http://
或 https://
域名(Domain) :例如,www.google.com
端口(Port) :例如,80
(默认HTTP端口)或443
(默认HTTPS端口)
同源策略就是:不允许不同的 ip、端口、协议的应用在浏览器内进行互相资源共享、请求调用。也就是说只有上述三个元素都匹配时,我们才会认为两个 URL 具有相同的来源,否则,有任何一个不相同都认为不同源。
具体式例:
4. 什么是 CORS?
CORS 是一种机制,它使用额外的 HTTP 头来告诉浏览器允许一个网页从另一个域(不同于该网页所在的域)请求资源。这样可以在服务器和客户端之间进行安全的跨域通信。
CORS有两种类型的请求:“simple” 简单请求和 “preflight” 预检请求,根据请求方法的不同由浏览器确定使用哪种请求。
simple 简单请求:
如果符合以下所有条件,则API请求被视为简单请求:
- API方法是以下方法之一:GET,POST或HEAD。
- Content-Type请求头包含:application/x-www-form-urlencoded,multipart/form-data,text/plain
对于 GET、HEAD 和某些 POST 请求,浏览器直接附加 Origin 头发送请求,服务器在响应中添加 CORS 相关字段即可,无需预检。如果您的API请求被视为 simple 简单请求,这个请求就可以直接被发送给服务器。服务器使用 CORS HTTP Headers进行响应,浏览器将检查 Access-Control-Allow-Origin 后决定这个请求是否可以突破同源策略的限制,进行下一步的处理。
preflight预检请求:
如果您的 API 请求不满足成为简单请求的标准(最常见不满足简单请求标准的Content-Type值为application/json),则浏览器将在发送实际请求之前发出预检请求。
当一个网页向不同源发出请求时,CORS 会通过以下几个步骤来处理:
- 预检请求(Preflight Request):对于某些类型的请求(如使用 HTTP 方法 PUT、DELETE,或者请求带有非简单头部),浏览器会首先发送一个 OPTIONS 请求,这个请求称为“预检请求”。服务器收到这个请求后,会返回一个响应头部,指明实际请求是否被允许。
- 实际请求(Actual Request):如果预检请求通过,浏览器会继续发送实际的请求。
- 响应头部(Response Headers):服务器在响应中会包含一些特定的 CORS 头部,如 Access-Control-Allow-Origin,以指示哪些域名可以访问资源。
举一个例子,我们尝试使用 GET 请求 https://example.com/status,Content-Type 是application/json,所以浏览器认为它不符合一个简单请求的标准,因此浏览器会在发出实际请求之前发出预检请求,这个预检请求是使用 HTTP 的 OPTIONS 方法发出的:
5. 如何处理 CORS
[]()服务端处理
后端设置响应头,允许特定源的请求。
设置基础响应头\
在服务器响应中添加以下头部:
Access-Control-Allow-Origin: <允许的源> # 如 "*"(允许所有)或 "https://example.com"
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS # 允许的HTTP方法
Access-Control-Allow-Headers: Content-Type, Authorization # 允许的请求头
Access-Control-Allow-Credentials: true # 允许携带凭证(如Cookie),需与具体源配合使用
处理预检请求(Preflight Request)\
对 OPTIONS
方法的请求返回允许的CORS头,无需处理业务逻辑:
// Express示例
app.options('/api', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', 'https://example.com');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.sendStatus(204);
});
代理服务器
通过同域的反向代理转发请求,避开浏览器限制。
步骤(以Nginx为例):
修改Nginx配置:
server {
listen 80;
server_name yourdomain.com;
location /api/ {
proxy_pass http://backend-server:3000/; # 转发到后端服务
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
前端请求同域接口(如 /api/data
),Nginx将请求代理到实际后端。
通常来说,在服务器解决 CORS 是一种比较常见和彻底的方式,我们可以在服务器灵活的设置允许跨域访问的域名或者地址。
6. 总结
CORS 是现代 Web 开发中常见的问题,理解 CORS 的工作原理,可以帮助我们有效地解决跨域请求的问题。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。