一、影响跨域的因素?
提起跨域,我们首先就会想到“同源策略”这四个字,没错,正是因为受同源策略的影响,我们才不能进行跨域请求,那么什么是“同源策略”呢?
二、同源策略到底是什么?
同源策略是一种约定,是一种安全策略,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响,web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现,所谓同源是指:域名、端口、协议相同。
下面认识一下在什么情况下是同源还是不同源,我们以“http://www.alberqing.com/1.html”为例:
url | 情况 | 结果 |
http://www.alberqing.com/zqys/2.html | 域名、端口、协议均相同 | 同源 |
http://www.alberqing.com/zqys1/2.html | 域名、端口、协议均相同 | 同源 |
http://www.alberqing.com:80/zqys1/2.html | 域名协议相同,端口不同 | 不同源 |
https://www.alberqing.com/1.html | 域名、端口相同,协议不同 | 不同源 |
http://en.alberqing.com/1.html | 端口、协议相同,域名不同 | 不同源 |
http://alberqing.com/1.html | 端口、协议相同,域名不同 | 不同源 |
http://en.www.alberqing.com/1.html | 端口、协议相同,域名不同 | 不同源 |
经过上述分析,我们可以想到,同源策略就限制了浏览器之间的跨域,那么我们该如何实现跨域?
三、跨域的几种实现方式
1、CORS(Cross-Origin Resource Sharing)
它是W3C的一个草案,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通。其背后的思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应应该是成功,还是失败
①IE对CORS的实现
引入XDR对象,这个对象与XHR类似,但能实现安全可靠的跨域通信。XDR对象和XHR对象有什么不同?
A、cookie不会随请求发送,也不会随响应返回。
B、只能设置请求头部信息中的Content-Type字段
C、不能访问响应头部的信息
D、只支持get和post的请求
它有效的缓解了CSRF和XSS问题,那么它如何使用?
A、get请求
var xdr = new XDomainRequest();
xdr.onload = function(){
alert(xdr.responseText);
};
xdr.onerror = function(){
alert("An error occurred");
};
xdr.open("get","http://www.alberqing.com/page/");
xdr.send(null);
B、post请求
var xdr = new XDomainRequest();
xdr.onload = function(){
alert(xdr.responseText);
};
xdr.onerror = function(){
alert("An error occurred");
};
xdr.open("post","http://www.alberqing.com/page/");
xdr.contentType = "application/x-www-form-urlencoded";
xdr.send("name1=value&name2=value2");
②其他浏览器对CORS的实现
A、跨浏览器的CORS
function createCORSRequest(method,url){
var xhr = new XMLHttpRequest();
if("withCredentials" in xhr){
xhr.open(method,url,true);
}else if(typeof XDomainRequest != "undefined"){
xhr = new XdomainRequest();
xhr.open(method,url);
}else{
xhr = null;
}
return xhr;
}
var request = createCORSRequest("get","http://www.alberqing.com/page/");
if(request){
request.onload = function(){
//对request.responseText
};
request.send();
}
③关于XMLHttpRequest对象和XDomainRequest的小总结(共同属性)
A、abort():用于停止正在进行的请求。
B、onerror():用于替代onreadystatechange检测错误
C、onload:用于替代onreadystatechange检测成功
D、responseText:用于取得响应内容。
E、send():用于发送请求
2、图像ping
我们知道,一个网页可以从任何一个网页中加载图像,不用担心跨域与否。这是在线广告跟踪浏览量的主要方式。可动态地创建图像,使用它们的onload和onerror事件处理程序来确定是否接收到了响应。
动态创建图像经常用于图像ping,它是与服务器进行简单的、单向的跨域通信的一种方式。请求的数据是通过查询字符串形式发送的,而响应可以是任意内容,但通常是像素图或204响应,通过图像ping,浏览器得不到任何具体的数据,但通过侦听load和error事件,它能知道响应是什么时候接到的
var img = new Image();
img.onload = img.onerror = function(){
alert("Done!");
};
img.src = "http://www.example.com/test?name=Nicholas";
图像ping技术最常用于跟踪用户点击页面或动态广告曝光次数。但是它有两个主要的缺点:
①只能发送get请求
②无法访问服务器的响应成本
因此,图像ping只能用于浏览器与服务器的单向通信
3、JSONP(由回调函数和数据组成)
JSONP是通过动态<script>元素来使用,使用时可为src属性指定一个跨域URL
function handleResponse(response){
alert(/*信息*/);
}
var script = document.createElement(script);
script.src="http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script,document.body.firstChild);
jsonp在开发人员中极为流行,就是因为它的简单易用,与图像Ping相比,它的优点是在于能够直接访问响应文本,支持在浏览器与服务器之间的双向通信。它的缺点:因jsonp是在其他域中加载代码执行,如果其他域不安全,可能会在响应中夹带一些恶意代码;还有一点就是确定它请求成功或者是失败并不容易
jsonp也只能使用get请求,因为src属性只能get请求
4、comet
它是一种更高级的Ajax技术,是服务器向页面推送数据的技术,它能够让信息近乎实时地被推送到页面上,非常适合处理体育比赛的分数和股票票价。
上述为四种常用跨域请求的方式,其实还有一些在此篇博客没有过多述说,我们需要根据需求合理的使用某种跨域方式。