详情参见: MDN HTTP访问控制 (CORS)
常用设置(一般情况够用了)
由 XMLHttpRequest
或 Fetch 发起的跨域 HTTP 请求
后端响应头设置:
-
配置允许跨域访问的源:
Access-Control-Allow-Origin: <origin> | *
- 允许所有源:
Access-Control-Allow-Origin: *
- 配置指定的源:
Access-Control-Allow-Origin: http://mozilla.com
- 不能同时指定多个源, 如有需要可以通过代码动态控制
- 允许所有源:
- 配置允许跨域访问的请求方法:
Access-Control-Allow-Methods: <method>[, <method>]*
- 配置允许跨域访问的请求头:
Access-Control-Allow-Headers: <field-name>[, <field-name>]*
如果需要附带身份凭证(携带cookie)则需要如下额外配置:
- 后端增加响应头:
Access-Control-Allow-Credentials: true
, 其中值固定为true
; - 前端请求库增加对应设置; (如axios中需要设置
withCredentials: true
即可发送cookie); - 对于这种附带身份凭证的请求, 服务器的
Access-Control-Allow-Origin
不能 设置为*
, 必须指定具体的origin;
代码动态控制允许多个域(以php为例)
// 允许跨域的origin白名单, 为空则允许所有origin跨域
$allowOrigin = []; // 如: ['http://localhost:8080', 'https://host:8081']
// 跨域访问的时候才会存在该字段
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
// 有配置白名单且当前origin在白名单
if (!empty($allowOrigin) && in_array($origin, $allowOrigin)) {
header("Access-Control-Allow-Origin: {$origin}");
}
注:
IE 10 提供了对规范的完整支持,但在较早版本(8 和 9)中,CORS 机制是借由 XDomainRequest 对象完成的。
扩展阅读(摘自MDN)
什么情况下需要 CORS ?
跨域资源共享标准( cross-origin sharing standard )允许在下列场景中使用跨域 HTTP 请求:
- 由
XMLHttpRequest
或 Fetch 发起的跨域 HTTP 请求。 - Web 字体 (CSS 中通过 @font-face 使用跨域字体资源), 因此,网站就可以发布 TrueType 字体资源,并只允许已授权网站进行跨站调用。
- WebGL 贴图
- 使用 drawImage 将 Images/video 画面绘制到 canvas
- 样式表(使用 CSSOM)
简单请求
某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”,请注意,该术语并不属于 Fetch (其中定义了 CORS)规范。若请求满足所有下述条件,则该请求可视为“简单请求”:
- 使用下列方法之一:
- GET
- HEAD
- POST
- Fetch 规范定义了对 CORS 安全的首部字段集合,不得人为设置该集合之外的其他首部字段。该集合为:
- Accept
- Accept-Language
- Content-Language
- Content-Type (需要注意额外的限制)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- Content-Type 的值仅限于下列三者之一:
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
- 请求中的任意
XMLHttpRequestUpload
对象均没有注册任何事件监听器;XMLHttpRequestUpload
对象可以使用XMLHttpRequest.upload
属性访问。 - 请求中没有使用
ReadableStream
对象。
预检请求
即好多同学初次接触感到奇怪的
OPTIONS
请求
与前述简单请求不同, “需预检的请求”要求必须首先使用 OPTIONS
方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。
当请求满足下述任一条件时,即应首先发送预检请求:
- 使用了下面任一 HTTP 方法:
- PUT
- DELETE
- CONNECT
- OPTIONS
- TRACE
- PATCH
- 人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:
- Accept
- Accept-Language
- Content-Language
- Content-Type (but note the additional requirements below)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- Content-Type 的值不属于下列之一:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- 请求中的
XMLHttpRequestUpload
对象注册了任意多个事件监听器。 - 请求中使用了
ReadableStream
对象。