javascript 跨域请求详细分析

什么是跨域请求

比如用户使用浏览器打开一个网站 (www.AAA.com)的首页,这个时候浏览器会执行来自网站www.AAA.com的一个javascript的函数,这个函数是向网站(www.BBB.com)请求数据:
$.getJSON(‘www.BBB.com/index.php‘, funciton(data) {
    // 后续操作
});
网站A的脚本去请求网站B的数据,就是跨域请求。在没有处理的情况下,浏览器会限制这样的请求。

同源策略

同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。这个策略可以追溯到 Netscape Navigator 2.0。如果两个页面的协议端口(如果指明了的话)和主机名都相同,Mozilla 认为这两个页面拥有相同的源。浏览器为什么要做这样的限制呢?
我们知道,JAVASCRIPT是很强大的,比如你打开了一个支付宝的网页,又一不小心打开了一个“病毒”网页,这个网页有一段Javascript,执行这段JS后,会修改了你的支付宝页面,后果可想而知。所以,浏览器阻止javascript请求非同源的脚本数据。

什么情况下,我们要绕过浏览器这个限制

情况1:CDN缓存导致的跨域请求。CDN服务器可以缓存网站服务器的javascript 文件,当浏览器向服务器请求数据的时候,如果需要请求javascript文件,浏览器首先会去CDN服务器中要,然后再由CDN服务器去网站服务器拿。加入一个CDN缓存后,就可以避免每次都向服务器某些文件。但是这样做,会有一个严重的问题,因为javascript文件是从CDN服务器中拿的,如果这个javascript需要向网站服务器请求数据,就会涉及到跨域的问题。

情况2:使用HTML构建APP应用,如果APP应用会有很多图片和文件,每次请求都向服务器请求这些图片和文件,实现的效果肯定不理想,而且特别耗流量.为了解决这个问题,我们可以把javascript保存在本地,然后通过访问文件的协议访问js文件,由这些js文件请求服务器的数据,更加数据的要求动态的构建html页面。访问形式类似与:
file:///E:/BaiduYunPan/www/test.js

情况3:网站A和网站B都是我的,我需要网站A中的Javascript能请求网站B的数据。

如何绕过浏览器这个限制

javascript 中src属性是不受同源策略限制的,因为这样,我们可以引用谷歌提供的Jquery文件。而且还记住一点,由src请求回来的数据,浏览器默认它是一段可执行的JS文件。在网站A中一个test.js:
<html>
<script>
function test(data)
{
    alert(data);
}
</script>
<script type="text/javascript" src="http://www.BBB.com/test.php"></script>
</html>

注意:test()函数必须声明在前。在网站B中有这个test.php文件:
<?php
echo "test(‘this data is from Server B‘)";

当浏览器执行到tes.js文件的时候,会触发test(data)这个函数,也就是说,可以请求到网站B的内容。这样,我们就已经实现了跨域请求数据。这个原理就是 src不受同源策略限制,会获取网站B响应的数据,而且会把这个数据当做JS文件来执行,所以,对于网站A来说,就是执行了test(data)函数。这个实现方式的重点就是网站B响应的数据是网站A中一段可执行的JS文件,这样网站A就可以处理来自网站B的数据了。

ajax自带jsonp属性实现跨域请求

jquery自带的ajax可以实现跨域请求,需求还是网站A中javascript向网站B请求数据。网站A中test.js的代码可以这样写:
   $.ajax({
        url:"www.BBB.com/index.php",   
        dataType:"jsonp",
        jsonpCallback:"person",
        success:function(data){
            alert(data.name + " is a a" + data.sex);
        }
   });
在网站B中有一个index.php文件
echo ‘person(‘ . json_encode(array(‘name‘ => ‘sunli‘, ‘age‘ => ‘24‘)) . ‘)‘;
这样就可以。

需要注意的是:
(1)jsonpCallback属性如果不指定,那么会有个随机的函数名, index.php输出数据的时候应该是这样:
echo $_GET[‘callback‘] . ‘(‘ . json_encode(array(‘name‘ => ‘sunli‘, ‘age‘ => ‘24‘)) . ‘)‘;

 (2)我在实现jsonp的时候,没有填写jsonpCallback, 在index.php中也没有加入$_GET[‘calllback‘]这样的函数名,于是就遇到一个很大的错误,网站A依然可以请求到网站B的数据,但是,test.js文件中,success 响应函数没有执行到,我想了半天都没有想到,为什么浏览器成功响应了数据,但是success却没有执行,最后由老大指出了问题,就是我第一点说的,没有指定回调函数,就算数据返回过来了,也不会执行success.





郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。