一、出现原因
跨域是指a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,或是a页面为ip地址,b页面为域名地址,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。
例如:
URL
说明
是否跨域
www.a.com/lab/a.js
www.a.com/script/b.js
同域名下不同文件
否
www.cnblogs.com/a.js
www.a.com/b.js
不同域名
是
www.a.com:8000/a.js
www.a.com/b.js
同域名下不同端口
是
同域名 不同协议
是
www.a.com/a.js
http://70.32.92.74/b.js
域名和域名对应ip
是
www.a.com/a.js
script.a.com/b.js
主域名相同 子域名不同
是
同一域名,不同二级域名(同上)
是
二、解决方案
【策略一】:Jsonp:需要目标服务器配合一个callback函数
JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
Json+padding(内填充),顾名思义,就是把JSON填充到一个盒子里,它的基本思想是,网页通过添加一个
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');