浏览器的同源策略,即是浏览器之间要隔离不同域的内容,禁止互相操作。
比如,当你打开了多个网站,如果允许多个网站之间互相操作,那么其中一个木马网站就可以通过这种互相操作进行一系列的非法行为,获取你在各个网站的相关信息,很明显这是不安全的,所以同源策略避免了很多这样的问题。
但是同时也带来了一些问题,比如有时候你想通过自己的网站去获取另一个自己的网站的一些资料信息,但是由于两者域名不同,所以就被同源策略隔离了,那么这个时候就需要了解一下浏览器的跨域问题。
跨域常见的两种方式,分别是jsonp和新推出的cors,即cross-origin resourse sharing,其实这货出现的时间也不短了,只是我现在才注意到而已。
先说说jsonp,先说个简单的例子再讲百度的例子。
我们有个www.a.com的页面
<script type="text/javascript"
src="http://www.b.com?name=qiangzi"></script>
<script type="text/javascript">
function jsonp(json){
alert(json[‘age’]);
}
</script>
这是请求 http://www.b.com?name=qiangzi 返回的js文件。
jsonp({'name':'qiangzi','age':20});
事先声明,个人没有实际的使用过jsonp去进行跨域操作,所以所有的分析都是猜想,若有不对请指出。
我们来试着去分析上面的代码,a页面事先写好了一个回调函数,即是供我们请求回的js回调的函数,这里的回调函数式alert参数组中的年龄。
我们再看我们的请求,首先我们的请求是写在script标签里面的,所以说明正常来说我们请求回来的内容应该是一段js文件。接着看,我们发现请求的时候同时传了一个参数过去name="qiangzi",所以我们基本可以猜测在www.b.com服务器那边,接收到a页面的请求,同时接收到传过来的name数据,根据这个数据进行相应的查询,找到了{name:"qiangzi",age:20}这样的一段数据之后,我们的b服务器于是就构造了一段这样的js文件传给请求的页面
jsonp({'name':'qiangzi','age':20});
也就是在原页面输出我们请求的name对应的年龄。很明显,我们请求的script标签中的src不能写死,而应该是一个动态的插入name值的过程。
从前台写好回调函数,到根据请求的参数值构造请求链接,跨域服务器根据链接进行相应处理返回数据并执行回调函数,这整一个过程就是jsonp的过程,当然上述只是我个人猜想,毕竟没有去实现过,所以有错望大神们指出。
那么我们按照这个思路再来看看百度搜索下拉框的jsonp跨域操作。
我们在百度搜索框输入jsonp,马上出现了下拉框,分别有jsonp json jsonp跨域等等,其实这一过程就是使用到了jsonp跨域处理,具体怎么过跨法,我们打开F12,找到network这里可以看到这样的一个请求
也就是这个链接
https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=jsonp&json=1&p=3&sid=19637_18286_1442_17711_18240_17944_19568_19806_19558_19808_19843_19861_17001_15825_12254&req=2&bs=xmlhttprequest&pbs=jsonp&csor=5&pwd=json&cb=jQuery1102032008872299992563_1463242088002&_=1463242088035
点击我们可以看到这样的一段东西
那么这样的一段东西其实是什么呢?其实这就是我们jsonp跨域请求回来的数据以及调用的函数。
接下来就按照我们刚才的思路分析下整个过程。
首先,百度在前台写好了一个回调函数,即是接收跨域返回来的数据并且出现下拉框,把数据填充到下拉框中。当我们在百度搜索的输入框(注意区分开此处的输入框和上句话中的下拉框)输入我们要搜索的内容时,此时百度页面马上获取我们输入的值,并构造请求,即我们上文中提到的
https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=jsonp&json=1&p=3&sid=19637_18286_1442_17711_18240_17944_19568_19806_19558_19808_19843_19861_17001_15825_12254&req=2&bs=xmlhttprequest&pbs=jsonp&csor=5&pwd=json&cb=jQuery1102032008872299992563_1463242088002&_=1463242088035
对于这一段请求,我个人看着都觉得有点怕怕的,所以为了方便理解jsonp我们简化下应该可以这样理解
https://sp0.baidu.com/su?wd=jsonp
服务器查询jsonp对应的联想关键词,并把这些关键词填充在一个数组中,然后把这个数组作为参数调用前台写好的回调函数,返回这段js文件给前台,然后我们就看到了在搜索框输入jsonp然后下拉框出现一系列关键词的功能。
至此,关于jsonp的例子讲诉差不多结束。那么jsonp有哪些优缺点呢?
jsonp的优点是兼容所有的浏览器,无论是主流的还是以前的。而它的缺点则是由于jsonp发起的请求是get方式的,即参数是填充在请求地址上,所以这种方式发送的数据有限制。
关于jsonp再补充点内容,其实不知道大家有没有想过,我们使用的很多API接口,调用他们返回的数据,其实这一过程就是跨域了,因为我们请求的是别的站点的数据,不做跨域处理我们是不可能获得信息的,只是有时候我们是按着API说明文档照写的所以忽视了这个
我这里有个国外的API,根据填写的邮编搜索邮编所对应的位置信息
http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=?
在这个API中我们需要填写三个参数,一个是邮编号码,另一个是对应的国家,而第三个就是我们的回调函数。
这个是该API接口返回的数据
整个API调用的过程就是,我们在前台写好一个callback函数,这个callback函数的功能就是根据我们的需求而写,然后在构造请求的时候把这个callback函数的名称写在请求对应的callback上。至于其他的邮编号码国家这些当然也是在我们前台页面构造的。构造完这些请求之后,当我们发起请求的时候,API服务器端就会根据我们的请求信息,拿到相应的数据,并把这些数据放到我们写的回调函数对应的参数中传回来,并进行调用,整个API调用完毕。
说完了jsonp,接下来说说cors跨域这玩意。
在前文看到同源策略的时候,不知道大家有没有想过,难道就不能让两个跨域的站点写一个秘密的协议,达成一种交易从而使得两者可以进行跨域操作获取数据之类的吗?嗯,我个人觉得cors做的就是这件事。
关于cors在*上的定义是这样的:跨域资源共享(CORS )是一种网络浏览器的技术规范,它为Web服务器定义了一种方式,允许网页从不同的域访问其资源。而这种访问是被同源策略所禁止的。CORS系统定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求。它是一个妥协,有更大的灵活性,但比起简单地允许所有这些的要求来说更加安全。
要想实现cors跨域,需要做的就是两件事,一个是我们的浏览器要支持cors跨域这一操作(主流谷歌和火狐均支持,ie版本要高于ie10才行),另外,我们的服务器端必须要设置好Access-Control-Allow-Origin从而支持跨域操作。
cors相对于jsonp而言的好处就是支持所有的请求方式,不止是get请求,还支持post,put请求等等,而它的缺点就很明显,无法兼容所有的浏览器,对于要兼容到老式浏览器而言,还是使用jsonp好点。