XHR 是受同源策略的限制,
跨源资源共享(CORS,Cross-Origin Resource Sharing)定义了浏览器与服务器如何实现跨源通信
CORS 基本思路
使用自定义的 HTTP 头部允许浏览器和服务器相互了解,以确实请求或响应应该成功还是失败。
对于简单请求,没有自定义头部,请求体为 text/plain 类型,发送请求时会有一个额外 Origin 头部。
Origin 头部包括包含发送请求的页面的源 (协议、域名和端口)
- Origin: http://www.nczonline.net
服务器会进行 决定可以跨域加发送 Access-Control-Allow-Origin 的头部,包含相同的源或者是“*”公开资源
- Access-Control-Allow-Origin: http://www.nczonline.net
XHR 使用 CORS 访问
现代浏览器通过 XMLHttpRequest 对象原生支持 CORS。在尝试访问不同源的资源时,这个行为 会被自动触发。要向不同域的源发送请求,可以使用标准 XHR 对象并给 open()方法传入一个绝对 URL
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("get", "http://www.somewhere-else.com/page/", true);
xhr.send(null);
跨源 XHR
对象些额外限制
- 不能使用 setRequestHeader() 设置自定义头部
- 不能发送和接收 cookie
getAllResponseHeaders() 方法始终返回空字符串
预检请求 preflighted request
CORS 通过预检请求通过 OPTIONS 方法对服务器验证
允许使用自定义头部
- 支持除 GET 和 POST 之外的方法,
- 不两只请求体内容
浏览器 OPTIONS 方法的头部
- Origin 与简单请求相同
- Access-Control-Request-Method 请求希望使用的方法
- Access-Control-Request-Headers (可选)要使用逗号分隔的自定义头部列表
服务器响应发送头部
- Access-Control-Allow-Origin 与简单请求相同
- Access-Control-Allow-Method 允许的方法(逗号分隔的列表)
- Access-Control-Allow-Headers 服务器允许的头部(逗号分隔的列表)
Access-Control-Max-Age 缓存预请求的,即第一次发送这种的请求时隔多久才会再发送一次额外的 HTTP 请求
凭据请求
默认跨源不提供凭据(cookie、HTTP 认证和客户端 SSL 证书),可通过 withCredentials 为 true 来表明请求会发送凭据。
服务器允许,响应 HTTP 头部Access-Control-Allow-Credentials: true
如果发送了凭据请求而服务器返回的响应中没有这个头部,则浏览器不会把响应交给 JavaScript
(responseText 空字符串,status 是 0,onerror()被调用)。
注意,服务器也可以在预检请求的
响应中发送这个 HTTP 头部,以表明这个源允许发送凭据请求。
替代性跨源技术
CORS 出现之前,实现跨源 Ajax 通信是有点麻烦的。开发者需要依赖能够执行跨源请求的 DOM 特 性,在不使用 XHR 对象情况下发送某种类型的请求。虽然 CORS 目前已经得到广泛支持,但这些技术 仍然没有过时,因为它们不需要修改服务器。