一、出现原因
跨域是指a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,或是a页面为ip地址,b页面为域名地址,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。
例如:
URL | 说明 | 是否跨域 |
http://www.a.com/lab/a.js http://www.a.com/script/b.js |
同域名下不同文件 | 否 |
http://www.cnblogs.com/a.js http://www.a.com/b.js |
不同域名 | 是 |
http://www.a.com:8000/a.js http://www.a.com/b.js |
同域名下不同端口 | 是 |
http://www.a.com/a.js https://www.a.com/b.js |
同域名 不同协议 | 是 |
http://www.a.com/a.js http://70.32.92.74/b.js |
域名和域名对应ip | 是 |
http://www.a.com/a.js http://script.a.com/b.js |
主域名相同 子域名不同 | 是 |
http://www.a.com/a.js http://a.com/b.js |
同一域名,不同二级域名(同上) | 是 |
二、解决方案
【策略一】:Jsonp:需要目标服务器配合一个callback函数
JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
Json+padding(内填充),顾名思义,就是把JSON填充到一个盒子里,它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
首先,网页动态插入<script>元素,由它向跨源网址发出请求。
JSONP的产生:
1.AJAX直接请求普通文件存在跨域无权限访问的问题,不管是静态页面也好.
2.不过我们在调用js文件的时候又不受跨域影响,比如引入jquery框架的,或者是调用相片的时候
3.凡是拥有scr这个属性的标签都可以跨域例如<script><img><iframe>
4.如果想通过纯web端跨域访问数据只有一种可能,那就是把远程服务器上的数据装进js格式的文件里.
5.而json又是一个轻量级的数据格式,还被js原生支持
6.为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback 参数给服务端
Js 客户端 方案一:
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <script type="text/javascript"> function jsonpCallback(result) { //alert(result); for(var i in result) { alert(i+":"+result[i]);//循环输出a:1,b:2,etc. } } var JSONP=document.createElement("script"); JSONP.type="text/javascript"; JSONP.src="http://crossdomain.com/services.php?callback=jsonpCallback"; document.getElementsByTagName("head")[0].appendChild(JSONP); </script>
Js 客户端 方案二:
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <script type="text/javascript"> function jsonpCallback(result) { alert(result.a); alert(result.b); alert(result.c); for(var i in result) { alert(i+":"+result[i]);//循环输出a:1,b:2,etc. } } </script> <script type="text/javascript" src="http://crossdomain.com/services.php?callback=jsonpCallback"></script>
Jquery 客户端 方案一:
<script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> $.getJSON("http://crossdomain.com/services.php?callback=?", function(result) { for(var i in result) { alert(i+":"+result[i]);//循环输出a:1,b:2,etc. } }); </script>
Jquery 客户端 方案二:
<script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> $.ajax({ url:"http://crossdomain.com/services.php", type:'get',//注意:跨域请求是只能是get请求不能使用post请求 dataType:'jsonp', data:'', jsonp:'callback',//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为:callback) jsonpCallback:"success",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名 success:function(result) { console.log(result); }, timeout:3000 }); </script>
Jquery 客户端 方案三:
<script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> $.get('http://crossdomain.com/services.php?callback=?', {name: encodeURIComponent('tester')}, function (json) { for(var i in json) alert(i+":"+json[i]); }, 'jsonp'); </script>
PHP 服务端:
//服务端返回JSON数据 $arr=array('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5); $result=json_encode($arr); //动态执行回调函数 $callback=$_GET['callback']; echo $callback."($result)";
【策略二】基于iframe实现的跨子域:通过修改document.domain来跨子域
将子域和主域的document.domain设为同一个主域.前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域
主域相同的使用document.domain
【策略三】PHP设置header头来实现跨域
//Access-Control-Allow-Origin:指定允许其他域名访问。该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。 header('Access-Control-Allow-Origin:*'); //Access-Control-Allow-Methods:响应类型 header('Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS'); //Access-Control-Allow-Headers:响应头设置 header('Access-Control-Allow-Headers:X-Requested-With,Content-Type'); //Access-Control-Expose-Headers:该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。 header('Access-Control-Expose-Headers:Authorization');