简介
如下图所示,当请求一个不同协议、不同域名或不同端口的资源时,就会发起跨域 HTTP 请求,出于安全考虑,浏览器默认会限制这些请求。但同时制定一个 CORS 标准来允许我们发起跨域请求。
CORS 全称为“跨域资源共享”(Cross-origin resource sharing),它允许浏览器向跨源服务器发出 XMLHttpRequest
或 fetch
等请求。
工作原理
CORS 请求分为简单请求与非简单请求两类。以下以 XMLHttpRequest
请求来解释跨域资源共享的工作原理。
简单请求
如果请求同时满足以下两个条件则视为简单请求,简单请求不会触发 CORS 预检。
1、请求方法为以下之一
- GET
- POST
- HEAD
2、HTTP 头信息不超出以下几种字段
- Accept
- Accept-Language
- Content-language
- Content-Type,只能为 text/plain、multipart/form-data、application/x-www-form-urlencoded
简单请求中,浏览器会直接发出 CORS 请求,具体过程就是在请求头中添加 Origin
字段。该字段说明请求来自哪里,使用协议+域名+端口表示,服务端根据该值决定是否同意此次请求。
GET /resources/access-control-with-get/ HTTP/1.1
Host: aruner.net
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Origin: http://arunranga.com
...
如果服务端允许 Origin
指定的域名进行请求,则必须在响应头中添加 Access-Control-Allow-Origin
字段,它允许以下两种值。
// 允许 Origin 指定的域名
Access-Control-Allow-Origin: http://arunranga.com
// or 允许所有域名请求
Access-Control-Allow-Origin: *
如果跨域成功,会返回类似以下响应头。
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61
Access-Control-Allow-Origin: http://arunranga.com
...
非简单请求
如果请求方法为 DELETE
或者设置 Content-Type
为 application/json
等,则浏览器会先发出预检请求。预检请求使用 OPTIONS
方法,并发送包含 Origin
与 Access-Control-Request-Method
的头信息,只有得到服务端的正确返回,浏览器才会发出真实的 XMLHttpRequest
请求,否则会报错。
预检失败会有如下报错信息。
XMLHttpRequest cannot load http://api.domaina.com.
Origin http://api.domainb.com is not allowed by Access-Control-Allow-Origin.