美文网首页
window.postMessage解决前端ajax跨域问题

window.postMessage解决前端ajax跨域问题

作者: 前端C罗 | 来源:发表于2018-12-07 00:22 被阅读11次

    postMessage畅快解决跨域问题

    本文主要是记录使用window.postMessage解决ajax跨域问题的方案,实践检验。

    window.postMessage简介

    window.postMessage 是一个安全的跨源通信的方法。一般情况下,当且仅当执行脚本的页面使用相同的协议(通常都是 http)、相同的端口(http默认使用80端口)和相同的 host(两个页面的 document.domain 的值相同)时,才允许不同页面上的脚本互相访问。 window.postMessage 提供了一个可控的机制来安全地绕过这一限制,当其在正确使用的情况下。

    跨域问题对于前端从业者而言绝对不会陌生,如果您是一位喜欢google或者百度的自学爱好者,必然会在检索的页面上看到不同的解决方案。这些解决方案从大类上来看,大致可分为前端解决方案,后端解决方案,前后联调解决方案。

    后端方案

    : 通过设置后端接口访问的权限,比如设置access-origin的源策略,让其设置为通配符*,或者发送请求的域名即可,最早的时候设置apache下的访问策略实践过,可解决跨域访问的问题。

    前后端联调方案

    : 后端通过返回特定代码片段的形式,前端通过jsonp方式发送请求,但由于是script的方式所以对于post请求无能为力,只能处理get类型。
    : 在页面上通过嵌套指定域名下的中转页面来进行接口调用,但是如果需要传递数据的话可通过window.name来保存并传输接口数据,本人未实践,各位可根据网友的方案自行测试,不赘述。
    : 在页面上通过iframe嵌套目标接口同域名下的页面,请求数据交给iframe页面,实际页面获取数据时,通过window.postMessage来跟iframe的页面进行数据交换。这也是本文要介绍的方案,实际验证可用。

    首先,可以一起来理解一下整个方案的思路和结构

    sequenceDiagram
    www.a.com/a.html->>www.b.com/b.html: 根据消息的源将本页面的url回发
    www.b.com/b.html-->>www.b.com/cgi: ajax请求
    www.b.com/cgi-->>www.b.com/b.html: cgi返回的数据
    www.b.com/b.html-->>www.a.com/a.html: post到a域下的a页面
    

    在实现的时候,现在a页面上获取嵌入的iframe的窗口对象,然后向其发送一条消息,消息体是a页面的url,但是具体实现的时候发现数据没发送过去,这个待排查。然后的解决方案就是b页面先广播一条数据,请求握手,然后a页面监听到消息后再根据消息源对象来发送指定数据,可行。

    具体示例代码如下:
    业务页面逻辑,这里的type为1时表示是握手消息,消息数据可忽略;当type为2时,表示是数据消息,消息体中的data属性为需要的数据内容

    window.addEventListener('message',function (event) {
        //alert('message comes');
        var origin = event.origin || event.originalEvent.origin;
        console.log(event.data);
        var ret = JSON.parse(event.data);
        if(ret.type == 1){
          //回复消息
          event.source.postMessage(window.location.href,origin);
        }
        if(ret.type == 2){
          console.log(ret);
        }
    },false);
    

    中转页面逻辑,先构造消息体,页面加载时先发送一条广播消息,跟业务页面进行握手;然后根据业务页面传递的参数来做相应的接口调用。

    //是否为第一次响应消息的标志
    var flag = true;
    var fWindow = window.parent;
    //var url = fWindow.location.href;
    var data = {
        //type为1时,表示是握手
        type : 1
    };
    //第一次握手,告诉父页面把相关信息发送过来
    fWindow.postMessage(JSON.stringify(data) ,'*');
    
    window.addEventListener('message',function (e) {
        if(!flag)
            return;
        var origin = e.origin || e.originalEvent.origin;
        console.log('data from father page ' + e.data);
    
        //返回验证信息
        e.source.postMessage(JSON.stringify(data),origin);
        //重置标志
        flag = false;
    });
    

    经过前后端调试,验证此方案可行,具体逻辑请自行修改相应的逻辑即可。希望对各位读者有用,也欢迎一起讨论。

    相关文章

      网友评论

          本文标题:window.postMessage解决前端ajax跨域问题

          本文链接:https://www.haomeiwen.com/subject/fyhzcqtx.html