首先先解释名词:
同源策略,浏览器的一种安全策略,只有域名协议端口完全一直才能访问。
http://www.liuyixiang.cn:80/a.html
协议 域名 端口
为什么会有这种策略呢?
大家看下下面的代码:
<iframe src="http:jd.com" frameborder="0"></iframe>
<script>
// 接下来,我们在本地添加一些操作,是不是就能获取相关私密信息了?
</script>
所以,处于安全的考虑,浏览器是不支持我们跨域访问其它页面的对象的。
也就是说:
1. 不允许跨域操作不同域的dom,(包括cookie)
2. 不允许跨域Ajax
可是在很多情况下,我们是需要跨域访问相关数据的,比如一个网站很大,比如说qq:
v.qq.com / email.qq.com ,不同域之间也要访问数据,该怎么办呢?
目前给大家解释三种解决办法:
1.代理服务器(后台技术,这里不作解释)
2.JSONP
3.document.domain 和 iframe
接下来就给大家介绍下document.domain 和iframe 是如何实现跨域的
//此方法解决跨域问题要求一级域名一致
//步骤:
//1. 首先要在不同域的两个文档里都设置:document.domain = 'liuyixiang.cn'
//2. 在父窗口中创建iframe,并将它隐藏
//假设路径是: http://blog.liuyixiang.cn/son.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p id="p1">需要被跨域访问的数据</p>
<script type="text/javascript">
document.domain = 'liuyixiang.cn';
</script>
</body>
</html>
//假设路径是: http://liuyixiang.cn/father.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
document.domain = 'liuyixiang.cn';
var iframe = document.createElement('iframe');
ifram.src = 'http://blog.liuyixiang.cn/son.html';
ifram.style.display = 'none';
document.body.appendChild(iframe);
iframe.onload = function(){
var doc = iframe.contentWindow.document || iframe.contentDocument;
// 这里就可以操作son.html了
// 比如说我们改变下字体颜色
doc.getElementById("p1").style.color = 'red';
// 当然,如果我们想操作father.html 就直接document
iframe.onload = null;
}
</script>
</body>
</html>
接下来在给大家介绍下jsonp是如何实现跨域的:(会有点难哦,需要懂一点点后台语言)
先来讲下jsonp的跨域原理:
实际上是利用JavaScript标签具有可跨域性的特点,由服务端返回一个预先定义好的JavaScript函数的调用,并将服务端数据以该函数参数的形式传递过来,此方法需要前后端配合来实现完成。
先来解释下JavaScript标签具有可跨域性的原因,我们写一个html文档需要jQuery框架时,引用别人写好的JQuery的CND,有没有想过跨域问题,哈哈,因为浏览器没有管,所以,JavaScript标签是具有可跨域性的,但我们导入JavaScript 时,src的后缀名并不能代表什么,关键是看服务器返回的文本内容,比如一个js文件也可以用.php结尾,只要我们指定了它的Content-type:text/javascrip,告诉浏览器返回的是JavaScript。如果返回的是一个事先声明好的函数调用,那么在这个函数调用过程中,将跨域请求的数据以实参传递过来,一般是json格式。
所以结合src的可跨域性和Content-type指定文档类型两个方面,就可以实现跨域了。
JSONP的本质就是服务端返回一个JavaScript函数调用,而这个函数事先已经本声明了。 有没有晕啊?2333把基本语法写出来大家瞧下
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
function jsonp(data){
//此处的data为跨域获得的数据,拿来就可以直接用了
}
</script>
<!--接下来是一个跨域请求,并传递参数-->
<!--
此处简单给大家介绍下后台代码:伪码说明下
首先后台先获取callback参数,然后执行
执行的时候,会把后台跨域需要访问的数据当作实际参数传入
-->
<script type="text/javascript" src="http://liuyixiang.cn/service.php?callback=jsonp"></script>
<!--
这样呢,用JavaScript实现就完成了
-->
</body>
</html>
注意:通过jsonp跨域请求只能用get方法,因为我们可以看到请求参数就在url中
接下来,介绍下在JQuery中如何Ajax实现跨域访问:
先介绍下Ajax请求的两种用法:
1.发起XMLHttpRequest
2.跨域访问
之前,我们已经介绍了在Jquey中如何运用Ajax,也就是第一种,现在我们来介绍下第二种
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!--首先肯定是要导入jQuery了233-->
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript">
$.ajax({
type:'post',
url:'htttp://liuyixiang.cn/service.php',
dataType:'jsonp', // 注意此属性为跨域访问的关键属性
// 解释:
// 当我们设置dataType:'jsonp'后,Ajax内部就不会再创建 XMLHttpRequest对象
// 而是在head中创建script元素,并自动设置属性src = url?callback=jsonp(随机生成)
// 来模拟之前js的写法
jsonp:'callback',//指定服务器端接受参数key的名称,默认为callback,此处要是更改,后台也要变化
jsonpCallback:'test',// 指定回调函数,默认会自动生成,test是预先定义好的函数,需要我们自己写。
// 一般情况下,最后这两种属性都不需要设置
success:function(data){
// data即为服务端传来的数据了
}
});
</script>
</body>
</html>
上面就是用Ajax 来实现跨域,接下来我们写一个小例子来看下:
ak是错的,大家不用试了,我们来调用下百度天气服务的PAI,只是一个用Ajax实现跨域的例子
<script type="text/javascript">
$.ajax({
type:"get",
url:'http://api.map.baidu.com/telematics/v3/weather',
dataType:'jsonp',
data:{
ak:'3L8K8EZ4NxUQ4QzxpI74cL3VCZzIX3ur',
location:'北京',
output:'json',
},
success:function(info){
// ..操作就行
}
});
</script>
请求参数:
data{
ak:'..',
location:'北京',
}
会自动处理的,
当我们把返回结果设置为json时,通过success:function(data){},data 即为我们要处理的json对象了。