利用jsonp、iframe和location.hash解决跨域问题

前端之家收集整理的这篇文章主要介绍了利用jsonp、iframe和location.hash解决跨域问题前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

几种解决js跨域的方法

js的跨域:由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一

当前页面地址不同即为跨域。如下示例:

URL 说明 是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js 同一域名下 允许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js 同一域名下不同文件夹 允许
http://www.a.com:8000/a.js
http://www.a.com/b.js 同一域名,不同端口 不允许
http://www.a.com/a.js
https://www.a.com/b.js 同一域名,不同协议 不允许
http://www.a.com/a.js
http://70.32.92.74/b.js 域名和域名对应ip 不允许
http://www.a.com/a.js
http://script.a.com/b.js 主域相同,子域不同 不允许
http://www.a.com/a.js
http://a.com/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不

允许访问)
http://www.cnblogs.com/a.js
http://www.a.com/b.js 不同域名 不允许

注意:对于端口和协议的不同,只能通过后台解决
解决办法:
1.script标签的形式:jsonp
2.document.domain
3.服务器代理 4.window.name
5.flash
6. html5 postMessage
7. iframe和location.hash

通过jsonp

在js中,我们直接用ajax中XMLHttpRequest对象请求不同域上的数据时,是不可以的,

不能跨域,但是,在页面上引入不同域上的js脚本文件是可以的,jsonp就是利用这个特

性来实现的。
例如,如果有个a.html页面,它里面的代码需要利用ajax获取一个不同域上的json数据

,那么a.html中的代码就可以这样写:

script type="text/javascript">
        function jonpCallBack(data){

        }
    </script>
   <script type="text/javascript" src="http://example.com/data.PHP? callback=jonpCallBack"></script>

或者自动创建js加入页面function createJs(sUrl){
            var oScript = document.createElement('script');
            oScript.type='text/javascript';
            oScript.src = sUrl;
            document.getElementsByTagName('head')[0].appentChild(oScript);

        }
        createJs('http://example.com/data.PHP?callback=jonpCallBack');

js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作

为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

PHP代码

<?PHP $callback = $_GET['callback'];//得到回调函数 $data = array('a','b','c');//要返回的数据 echo $callback.'('.json_encode($data).')';//输出 ?>

最终,输出结果为:jonpCallBack([‘a’,’b’,’c’]);

如果使用jQuery,通过它的封装方法就能很方便的来才操作jsonp了。

<script type="text/javascript"> $.getJSON('http://example.com/data.PHP?callback=?,function(jsondata)'){ //处理获得的json数据 }); </script>

jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自

动销毁,实际上就是起一个临时代理函数的作用。$.getJSON方法自动判断是否跨域,

不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用

jsonp的回调函数

利用iframe和location.hash:

这个方法也可以解决完全跨域情况下的问题,利用location.hash来进行传值。在url:

http://a.com#helloword中的‘#helloworld’就是location.hash,改变hash并不会导

页面刷新,所以可以利用hash值来进行数据传递,当然数据容量是有限的。假设域名

a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html传递信息,cs1.html首先创

自动创建一个隐藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html页面

这时的hash值可以做参数传递用。cs2.html响应请求后再将通过修改cs1.html的hash值

来传递数据(由于两个页面不在同一个域下IE、Chrome不允许修改

parent.location.hash的值,所以要借助于a.com域名下的一个代理iframe;Firefox可

修改)。同时在cs1.html上加一个定时器,隔一段时间来判断location.hash的值有没

有变化,一点有变化则获取获取hash值。代码如下:
先是a.com下的文件cs1.html文件

function startRequest(){
    var ifr = document.createElement('iframe');
    ifr.style.display = 'none';
    ifr.src = 'http://www.cnblogs.com/lab/cscript/cs2.html#paramdo';
    document.body.appendChild(ifr);
}

function checkHash() {
    try {
        var data = location.hash ? location.hash.substring(1) : '';
        if (console.log) {
            console.log('Now the data is '+data);
        }
    } catch(e) {};
}
setInterval(checkHash,2000);

cnblogs.com域名下的cs2.html:

//模拟一个简单的参数处理操作
switch(location.hash){
    case '#paramdo':
        callBack();
        break;
    case '#paramset':
        //do something……
        break;
}

function callBack(){
    try {
        parent.location.hash = 'somedata';
    } catch (e) {
        // ie、chrome的安全机制无法修改parent.location.hash,
        // 所以要利用一个中间的cnblogs域下的代理iframe
        var ifrproxy = document.createElement('iframe');
        ifrproxy.style.display = 'none';
        ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata';    // 

注意该文件"a.com"域下
        document.body.appendChild(ifrproxy);
    }
}

a.com下的域名cs3.html

//因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值
parent.parent.location.hash = self.location.hash.substring(1);

当然这样做也存在很多缺点,诸如数据直接暴露在了url中,数据容量和类型都有限等

猜你在找的Json相关文章