跨域CORS的情缘~

文章主要内容来自这篇文章

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来访问数据时候不需要做任何数据访问逻辑的更改,所有的工作都是服务端以及浏览器间自动完成。主要的工作在服务端,需要进行配置。

猜你喜欢

转载自blog.csdn.net/qq_33589252/article/details/83987571