文章主要内容来自这篇文章
cors:完成资源的跨域访问 。
相同的协议,主机地址以及端口号才能够进行访问。
业界中提出了一些解决该问题的方法:domian属性,跨文档消息,JSONP,以及CORS等~
方案各有长处,根据不同的需求来对方案选择。
domain
直接快速的方法,较为常见。不同域中得到脚本的domain属性设置为同一值,就能使这些脚本进行交互。
document.domain="icodehub.cn";
跨文档的消息
通过向window实例发送消息来完成的。在使用时,调用postMessage()函数发送消息。window内部的onmessage事件被触发,进而该事件的消息处理函数被调用。消息处理函数首先需要判断消息来源的合法性,以避免恶意用户通过发送消息的方法来非法执行代码。
JSONP
通过script标签来从另一个域中返回数据。
<script src="http://www.icodehub.cn?callback=some_func"></script>
会指向http://www.icodehub.cn发送一个GET请求,在数据返回客户端,some_func函数会被调用。只支持GET。
CORS
Simple Request
想象想别的域发送请求:
function retrieveData() {
var request = new XMLHttpRequest();
request.open('GET', 'http://public-data.com/someData', true);
request.onreadystatechange = handler;
request.send();
}
支持cors协议的服务会给出响应:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://www.icodehub.cn
Content-Type: application/xml
有一个响应头Access-Control-Allow-Origin。用来记录可以访问该资源的域。
在接收到服务端响应后,浏览器查看响应中是否包含Access-Control-Allow-Origin。
如果存在,浏览器将会分析该响应头中所标示内容。如果包含了当前页面所在的域,那么浏览器将知道允许跨域访问。
CORS则将导致跨域访问的请求分为三种:Simple Request,Preflighted Request以及Request with Credential。
如果一个请求没有包含任何自定义的请求头,所使用的HTTP动词是GET,HEAD,POST之一,那么他就是Simple Request。但是POST作为请求动词时centent-type需要设置:application/x-www-form-urlencoded,multipart/form-data或text/plain之一。
如果包含了自定义的请求头,或者他使用的HTTP动词时HEAD,GET,POST之外的,那么就是Preflighted Request。如果POST请求的content-type并不是application/x-www-form-urlencoded,multipart/form-data或text/plain之一,那么也是Preflighted Request。
一般情况下,一个跨域请求不会包含当前页面的用户凭证。
跨域包含了当前页面的凭证,其属于Request with Credential。
Preflighted Request
发送一个post请求:
function sendData() {
var request = new XMLHttpRequest(),
payload = ......;
request.open('POST', 'http://public-data.com/someData', true);
request.setRequestHeader('X-CUSTOM-HEADER', 'custom_header_value');
request.onreadystatechange = handler;
request.send(payload);
}
首先发出的并不是post请求,而是option请求。该请求通过Access-Control-Request-Method以及Access-Control-Request-Headers标示了请求类型以及请求中所包含的自定义HTTP Header。进行访问资源前发送一个请求进行探测。
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://ambergarden.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-CUSTOM_HEADER
Access-Control-Max-Age: 1728000
浏览器分析响应并了解到其被允许向服务端发送数据以后,才会发送真正的POST请求。
服务端则会接受并处理请求。
Request with Credential
在发送请求的时候,需要将用户凭证包含在请求内。
function retrieveData() {
var request = new XMLHttpRequest();
request.open('GET', 'http://public-data.com/someData', true);
request.withCredentials = true;
request.onreadystatechange = handler;
request.send();
}
服务端的响应中,其将拥有一个额外的Access-Control-Allow-Credentials响应头。
集成CORS支持,使用cors来访问数据时候不需要做任何数据访问逻辑的更改,所有的工作都是服务端以及浏览器间自动完成。主要的工作在服务端,需要进行配置。