跨域源资源共享
同源:域名、端口、协议均相同
CORS基本思想是使用自定义的HTTP头部,让服务器能声明允许访问的来源。
使用CORS时,异步请求会被分为简单请求(非Preflight)和非简单请求。
简单请求
所有的跨域请求(简单或非简单)总会包含一个origin的请求头部,由浏览器添加不受用户控制。值由协议、域名、端口组成,说明请求的来源。下面为一个Origin头部示例:
Origin:http://www.hello.com
服务器接受这个请求,会在响应头Access-Control-Allow-Origin
回发相同的源信息。( * 表明该资源可以被任意外域访问)
Access-Control-Allow-Origin:http://www.hello.com
非简单请求
非简单CORS请求会在正式请求之前发送一次Preflight
请求,得到确认之后才会发送真正的XMLHttpRequest请求。浏览器自动处理这两个请求,并且Preflight请求结束后,结果将按照响应中指定的时间缓存起来.所以只是第一次发送这种请求时会多一次HTTP请求. Preflight
请求使用OPTIONS方法,发送下列头部:
Origin:与简单请求相同
Access-Control-Request-Method:请求自身使用的方法
以下是一个带有自定义头部Custom-Header
的使用POST方法发送的请求.
Origin:http://www.hello.com
Access-Control-Request-Method:POST
Access-Control-Request-Headers:Custom-Header
var url = 'http://www.hello.com';
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Custom-Header', 'value');
xhr.send();
服务器通过在响应中发送如下头部与浏览器沟通:
Access-Control-Allow-Origin:http://www.hello.com
Access-Control-Allow-Methods:POST,GET
Access-Control-Allow-Headers:Custom-Header
Access-Control-Allow-Max-Age:28000 //表示将Preflight缓存的时长(秒),期间内无需再次发送预请求
另外通过将XMLHttpRequest的withCredentials属性设置为true就可以发送带凭据(cookie、HTTP认证、客户端SSL证明等)的跨域请求.
var xhr=new XMLHttpRequest();
xhr.withCredentials=true;
如果服务器接受带凭据的请求会用下面的HTTP头部响应:
Access-Control-Allow-Credentials:true
JSONP(JSON with padding)
JSONP由两部分组成:回调函数+数据,回调函数是当响应到来时应该在页面中调用的函数,回调函数的名字一般是在请求中指定的.而数据就是传入回调函数中的JSON数据.JSONP是通过动态元素,为其src属性指定一个跨域的URL.
function doSomething(response) {
console.log(response);
}
var script=document.createElement('script');
script.src='http://www.hello.com?callback=doSomething';
document.body.insertBefore(script,document.body.firstChild);
1.定义方法doSomething,然后把doSomething传给服务器,告知服务器我需要调用doSomething方法.
2.服务端生成JSON.将JSON数据以参数的形式放到doSomething中,这样就生成了一段js脚本返回给客户端.
3.客户端浏览器解析script标签,执行doSomething(JSON)
postMessage
otherWindow.postMessage(message, targetOrigin);
otherWindow:指目标窗口,也就是给哪个window发消息,是window.frames属性的成员或者由 window.open 方法创建的窗口.
参数说明:message: 是要发送的消息,类型为 String、Object (IE8、9 不支持);targetOrigin: 是限定消息接收范围,不限制请使用*