什么是跨域?
说跨域之前先要谈几个概念。跨域问题要从同源策略谈起,那什么是同源策略呢?
同源是下面三项都相同,缺一不可
协议+域名+端口
如果不同源,只可以引用css、js、php等文件,但不可以读写这些资源,这就是同源策略最通俗的描述。
看个浏览器报错例子:
我利用SAE同一项目下的两个域名http://1.georgema.applinzi. com
和http://2.georgema.applinzi.com
(注意这两个域名是不同源的)发送ajax
请求,在浏览器中可以看到报错。
如果我们要打破这个限制就需要跨域。
实现跨域有很多种方法,下面介绍几种:
跨域方法
第一种:降域
降域通俗地讲就是把域名变成符合同源的。
-
document.domain
的设置规则:- 只能设置为比它更高级的域名,www.a.first.com的
document.domain
可设置为 a.first.com ,也可以是 first.com ,但不可以是 google.com - 假设www.a.first.com的
document.domain
被设置为 first.com 就不能再向下重新设置为 a.first.com
- 只能设置为比它更高级的域名,www.a.first.com的
//以2.georgema.applinzi.com为例
<body>
<iframe src='//1.georgema.applinzi.com/'></iframe>
<h1>
跨域测试
</h1>
<script>
//这里的domain只能设置为上级的域名
document.domain='georgema.applinzi.com';
var ifr=window.frames;
ifr.onload=function(){
// to do...
}
</script>
</body>
//同时1.georgema.applinzi.com中也要设置domain
<script>
document.domain='georgema.applinzi.com';
function(){
//to do...
};
</script>
- 这种方法的局限性很大,一般只用来解决不同
iframe
之间的通信 - 降域之后上级域名下所有子域的安全性受到威胁
第二种:JSONP
- 这种方法利用的是浏览器允许
script
跨域 - 动态添加的
script
中加入json格式数据,实现数据读写
先看怎么实现动态script
//在2.georgema.applinzi.com里读取www.1.georgema.applinzi.com/user.js传回的json数据
var script = document.createElement('script');
window.getUsername = function(data){
var p = document.createElement('p');
p.innerText='username: '+data.name;
document.body.appendChild(p);
}
script.src="//1.georgema.applinzi.com/user.js?callback='getUsername''";
document.body.appendChild(script);
//www.1.georgema.applinzi.com/user.js中的json
getUsername({
'name': 'Nicholas'
})
发送ajax得到json数据(和上面方法是一样的,都是利用get请求返回json数据)就是 JSONP方法了
$.ajax({
url:'//1.georgema.applinzi.com/user.js',
dataType:'jsonp',
jsonpCallback:'getUsername',
success:function(){
onSuccess();
}
error:function(){
onError();
}
});
function getUsername(data){
var p = document.createElement('p');
p.innerText='username: '+data.name;
document.body.appendChild(p);
}
function onError(){
alert('连接出错');
}
- 这种方法的缺点:
- 容易被注入恶意代码,解决方案是服务器端加入字符串过滤
- 一般需要token验证,不让第三方访问
- 只能发送
GET
请求
第三种:CORS方法
CORS方法是在服务器对接受的来源域进行设置。Access-Control-Allow-Origin
可以指定接受请求的具体域名,也可也设置为*
表示所有源的请求都可以
//CORS方法,2.georgema.applinzi.com发送post请求
$.ajax({
url:'//1.georgema.applinzi.com/test.php',
type:'POST',
data:'georgema',
error:function(){
alert('连接错误!');
},
success:function(res){
alert(res);
}
});
//1.georgema.applinzi.com/test.php
<?php
header('Access-Control-Allow-Origin:http://2.georgema.applinzi.com'); //加这一句可以接收指定源的请求
echo 'hello';
?>
- 这种方法的缺点:
- 现代浏览器支持比较好,老版本浏览器不支持
- 需要后端支持
以上内容参考饥人谷教程