6种跨域获取数据的方法

一、基础引导

(1)通过Ifram获取数据

通过Ifram的contentWindow获取index2.html数据

//index1
<iframe src="index2.html" id="myIframe"></iframe>
<script type="text/javascript">
    var myIframe = document.getElementById('myIframe');

		window.name = 'mainWindow';

    myIframe.onload = function(){
        console.log(myIframe.contentWindow.name); //iframWindow
    }
</script>

//index2
<script type="text/javascript">
    window.name = 'iframeWindow';
</script>  

用Ifram加载一个页面,Ifram就是这个页面的窗口,可以通过.contentWindow获得这个窗口对象


父窗口访问子窗口通过.contentWindow,子窗口访问父窗口通过.parent

通过.parent来访问父窗口的name,此时window指向Index2

//index2
<script type="text/javascript">
    <iframe src="index3.html" id="myIframe"></iframe>
    window.name = 'iframeWindow';
    var iframe = document.getElementById('myIframe');
    iframe.onload = function(){
        console.log(window.parent.name); //mainWindow
    }
</script> 

通过.parent.parent来访问父窗口的name,此时window指向Index3

//index3
<script type="text/javascript">
        console.log(window.parent.parent.name); //mainWindow
</script> 

index2相当于index的儿子,index3相当于index的孙子

(2)window共享性

window.name是具有共享性的,在同一个窗口不同的页面是可以共享的 ,而且可以随意的读写

//index1
<script type="text/javascript">
    window.name="window";
    location.href = "index2.html" //跳转到index2页面
</script> 

//index2
<script type="text/javascript">
    console.log(window.name) //window
</script> 

这样是会报错的,两个页面的源不同就会受到同源策略的限制

//index1
<iframe src="http://....index2.html" id="myIframe"></iframe> //不同源的地址
<script type="text/javascript">
    var myIframe = document.getElementById('myIframe');
    myIframe.onload = function(){
        console.log(myIframe.contentWindow.name);
    }
</script> 

iframe之间的window.name是共享的,而主页面获取不同源的frame页面window.name是不行的

二、跨域

(1)服务器中转跨域

同源策略只针对浏览器,服务器之间没有跨域限制
在这里插入图片描述

在同源的服务器里面写一个程序,让服务器请求不同源的数据(后端程序中转)

(2)domain跨域

先设置主页面和frame页面的基础域名,再通过frame窗口拿到AJAX请求的接口,再通过这个接口发起HTTP请求
在这里插入图片描述

//index1
document.domain = "xxx.com";
var iframe = document.createElement('iframe');
iframe.src = "http://test.xxx.com/index.html";
iframe.id = "myIframe";
iframe.style.display = "none";
iframe.onload = function(){
    var $$ = document.getElementById('myIframe').contentWindow.$;
    $$.post('http://test.xxx.com/get.php',{status:1},function(data){})
}
document.body.appendChild(iframe);
 
//index2
document.domain="xxx.com"

封装

var ajaxDomain =(function(){
    function createIframe(frameId, frameUrl){
        var frame = document.createElement('iframe');
        frame.src = frameUrl;
        frame.id = frameId;
        frame.style.display = 'none';
        return frame;
    }
    return function(opt){
        document.domain = opt.basicDomain;
        var frame = createIframe(opt.frameId,opt.frameUrl);
        frame.onload = function(){
            var $$ = document.getElementById(opt.frameId).contentWindow.$;
            $$.ajax({
                url:opt.url,
                type:opt.type,
                data:opt.data,
                success:opt.success,
                error:opt.error
            })
        }
        document.body.appendChild(iframe);
    }
})();
 
//调用
ajaxDomain({
    basicDomain:'xxx.com', 
    frameUrl:'http://test.xxx.com/index.html', 
    url:'http://test.xxx.com/get.php', 
    type:'POST',
    data:{
        status:1
    },
    success:function(data){},
    error:function(data){}
})

(3)window.name跨域

先让iframe中的页面程序保存window.name,然后跳转与父级别窗口同源的另一个页面,父级页面可以从当前的iframe拿到该页面的window.name

window.name的特点:

  1. 每个浏览器窗口都有一个全局变量window(包含iframe的contentWindow)
  2. 每个window对象都有一个name属性(注意:一个窗口只有一个name属性)
  3. 该窗口被关闭前,所有页面共享一个name属性并拥有读写权限
  4. 无论该窗口在被关闭前,载入什么页面,都不会改变name值
  5. 存储约为2M字符串
  6. 如果父级窗口地址源和iframe地址源不同,父级无法通过ifram.contentWindow.name获取值,但iframe内部不受该规则限制
    在这里插入图片描述
//index1
var flag = false;
var iframe = document.createElement('iframe');
var getDatas = function(){
    if(flag){
        var data = iframe.contentWindow.name;
    }else{
        flag = true;
        setTimeOut(function(){
            iframe.contentWindow.loaction ='index2.html';//加载完后,就会再次触发onlaod事件,此代码块执行两次
        },500); // 延迟500毫妙为AJAX请求争取时间
    }
}
iframe.src = 'http://xxx.com/index.html';
if(iframe.attachEvent){
    iframe.attachEvent('onload',getDatas);
}else{
    iframe.onload = getDatas;
}
document.body.appendChild(iframe);
 
//index2
空 与index1同源 //iframe不管怎么跳转都可以获得window.name,这里跳转到与index1同源的地址

//index3
   $.post{'http:xxx.com/get_courses.php',{
     status:1
   }, function(data){
       window.name = JSON.stringify(data);
   }}

主页面只能获取同源的frame页面的window.name,而frame之间的window.name是共享的,不受同源策略影响。那么可以通过把frame跳转的地址设置为与主页面同源的地址,即可实现window.name跨域请求

(4)Postmessage跨域

不常用的原因:

  1. 伪造数据端漏洞
  2. xss攻击
  3. 兼容性问题

变量参数: otherWindow.postMessage(message,targetOrigin)

otherWindow: 接收方的引用

message: 要发送到接受方的数据

targetOrigin: 接收方的源,还有必需要有监听的message事件
在这里插入图片描述

//index1
<iframe src="http://text.xxx.com/index.html" id="iframe"></iframe>
<script type="text/javascript>
 window.onmessage = function(e){ //等待接收数据
     var e = e || window.event;
     console.log(JSON.parse(e.data));
 }
 
//index2
$.post('http://test.xxx.com/get.php',{status:1},function(data){
    window.name= JSON.stringify(data); //只能传字符串
    window.parent.postMessage(JSON.stringIfy(data),'http://index1.html'); //发送数据和接收地址源
}) 

(5)Hash跨域

基本原理: 利用url的hash值#xxx来传递数据
基础工具: location.hash
在这里插入图片描述

//index1
<button id= "btn">获取HASH</button>
<iframe src="http://test.xxx.com/index2.html#getCourses" id='cc' />
<script type="text/javascript">
    var oBtn = document.getElementById('btn');
    oBtn.onclick = function(){
        console.log(JSON.parse(decodeURI(location.hash.substring(1))))
    }
</script>

//index2
<iframe src="http://test2.xxx.com/index3.html" id="iframe" ></iframe>
var hash = location.hash.substring(1),
    iframe = document.getElementById('iframe');
switch(hash){
    case 'getCourses':
        $.post('htttp://xxx.com/get.php',{},function(){
            var str = JSON.stringify(data);
            iframe.src = "http://xxx.com/index3.html#"+str;
        })
}    
 
//index3 与index1 同源
setTimeout(function(){
    parent.parent.location.hash = self.location.hash.substring(1);
},300)

(6)Cors跨域

“跨域资源共享”(Cross-origin resource sharing)

Access-Control-Allow-Origin

  1. 任意域名:header("Access-Control-Allow-Origin;*");
  2. 单域名:header("Access-Control-Allow-Origin;http://test2.jsplusplus.com");
  3. 多域名:$allowed_origins = array('http://test2.jsplusplus.com','http://test3.jsplusplus.com');
    header("Access-Control-Allow-Origin:".$allowed_origins);

Access-Control-Request-Methods
通知服务器在真正的请求中会采用哪种HTTP方法
header("Access-Control-Request-Methods;GET,POST");

在服务端设置请求跨域的头信息header("Access-Control-Allow-Origin;xxx)、header(“Access-Control-Request-Methods;GET,POST”)的方式叫Cors跨域

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值