JavaScript解决跨域的几种方式

js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。一般情况下浏览器会阻止这些请求,认为这是不安全的,有以下几种解决措施

一、通过jsonp跨域

在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。

比如,有个页面,它里面的代码需要利用ajax获取一个不同域上的json数据,假设这个json数据地址是http://test.com/data.php,那么该页面中的代码就可以这样:

function getData(){
    console.log(data);
}
<script src="http://test.com/data.php?callback=getData"></script>
当然也可以使用jQuery的ajax跨域操作实现跨域,具体实现如下:
$(function(){
    $.ajax(
            {
                type:'get',
                url : 'http://www. .com/validate.php?loginuser=lee&loginpass=123456',
                dataType : 'jsonp',
                jsonp:"jsoncallback",
                success  : function(data) {
                    alert("用户名:"+ data.user +" 密码:"+ data.pass);
                },
                error : function() {
                    alert('fail');
                }
            }
    );
})

二,iframe 跨域

页面中增加一个iframe元素,在需要调用get请求的时候,将iframe的src设置为get请求的url即可发起get请求的调用。
var url = "xxx";
$("#iframe").attr("src", url);//跨域,使用iframe
iframe方式强于jsonp,除了可以处理http请求,还能够跨域实现js调用。

三,通过修改document.domain来跨子域

我们只要把http://www.example.com/a.html 和 http://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com 中某个文档的document.domain 可以设成a.b.example.com、b.example.com 、example.com中的任意一个,但是不可以设成 c.a.b.example.com,因为这是当前域的子域,也不可以设成baidu.com,因为主域已经不相同了。

四,window.name来跨域

Window.name属性是保存在浏览器端的,window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置

a页面设置window.name属性:

window.name="你好";
b页面访问该属性:

alert(window.name);
但要保证在同一个窗口下访问两个不同的页面。

五,window.postMessage实现跨域

postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
postMessage(data,origin)方法接受两个参数
 1.data:要传递的数据,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化。

2.origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,这个参数是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然如果愿意也可以建参数设置为"*",这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

3.在发送数据窗口执行:otherWindow.postMessage(msg,origin)
otherWindow:表示接受数据的窗口的window对象,包括iframe的contentWindwohe和通过window.open打开的新窗口。
msg表示要发送的数据,包扩字符串和对象(ie9以下不支持,可以利用字符串和json互换)。
origin表示接收的域名。
4.在接受的窗口监听window的message事件,回掉函数参数接受一个事件对象event,包括的属性有:
data:接受的数据
origin:发送端的域
source:发送端的DOMWindow对象

示例代码如下:

1.在父框架页面index.html发送obj对象给远程服务器的b.html,该页面是通过iframe加载的,如下

<!DOCTYPE html>
<html>
<head>
    <title>window.postMessage</title>
</head>
<body>
<iframe id="proxy" src="http://test.com/b.html" onload = "postMsg()" style="display: none" ></iframe>
<script type="text/javascript">
    var obj = {
        msg: 'this is come from client message!'
    }

    function postMsg (){
        var iframe = document.getElementById('proxy');
        var win = iframe.contentWindow;
        win.postMessage(obj,'http://test.com');
    }

</script>
</body>
</html>  

2.在远程页面b.html中监听message事件,先通过origin属性判断下数据来源的域是否可信任,加强安全措施。具体代码如下:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript">
        window.onmessage = function(e){
            if(e.origin !== 'http://localhost') return;
            console.log(e.origin+' '+e.data.msg);
        }
    </script>
</head>
<body>
<p>this is my server</p>
</body>
</html>  
3.在控制输出结果:

除了以上几种方法外,还有flash、在服务器上设置代理页面等跨域方式,之后会继续补充完善。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值