iframe跨域通讯解决方案

需求: 网站B内嵌套网站A的功能, 网站A有自己的登陆系统, 网站B也有自己的登陆系统, 要求, 网站B内打开A的里面的功能时, 免登陆

分析: 刚开始听到这个需求, 这个和我应该没有太大关系, 后端兼容一下token, 我稍微支持一下应该就ok了吧

实际: 后端说兼容不了token, 两边登陆系统不一样, 所以决定由前端, 根据打开的url来做处理


于是本着不懂就要学的精神开始了我的探索(以下讨论属于跨域的情况下).


方案1: 不需要传值, iframe拿到外层的host来进行判断.拿到host的方法如下

var url = null;

        if (parent !== window) {

            try {

                url = parent.location.href;

            } catch (e) {

                url = document.referrer;

            }

        }

return url;

在拿到外层url的时候还有一个系统的方法, 不过不是所有的浏览器都支持的, location.ancestorOrigins;可以直接获取到外层的host, 

火狐和fireforx和internetExplorer没有浏览器没有去找合适的方法, 有小伙伴告知, 感激不尽.....

评价: 拿到外层的host之后, 就是一些逻辑处理, 这个样子好吗? 根据host来判断感觉比较危险, 代码中写了一大片的逻辑, 后来者维护的时候可能不知道这个是要嵌入到别的网站的页面(必要的备注, 也不一定会被对方留意到), host以后改变了呢? 如果从外面传参过来会不会好一点? 废话少说, 先实践一波, 毕竟我爱学习


我爱学习



方案2: 从外层传值给iframe

1.postMessage API说明 

The window.postMessage() method safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.

Normally, scripts on different pages are allowed to access each other if and only if the pages they originate from share the same protocol, port number, and host (also known as the "same-origin policy"). window.postMessage() provides a controlled mechanism to securely circumvent this restriction (if used properly). (顺带学点英语)

简单方便, 可以解决 页面和其打开的新窗口的数据传递 ,多窗口之间消息传递, 页面与嵌套的iframe消息传递的跨域问题

demo必要代码如下:

B页面:

<iframe id="iframe_ID" src="http://localhost:8082/#/home" class="iframe"></iframe>

var iframe = document.getElementById("iframe_ID");

    iframe.onload = function() {

      var data = {

        name: '孩子, 我来看你了'

      }

      iframe.contentWindow.postMessage(JSON.stringify(data), 'http://localhost:8082/#/home');

    }

A页面:

const receiveMessage = (event) => {

            console.log(event.data);//孩子, 我来看你了

    };

 window.addEventListener('message', receiveMessage, false);

接收到B页面的信息

当然也可以实现A页面向B页面传值:window.parent.postMessage({haha:'最近还好吗'}, 'http://localhost:8081');

2.在A页面加参数, B页面获取到; 根源https://developer.mozilla.org/en-US/docs/Web/API/Location/search

The search property of the Location interface is a search string, also called a query string; that is, a USVString containing a '?' followed by the parameters of the URL.

可以获取到?后面的参数var data = location.search.split("=")[1];获取第一个参数

单向传值直接这一个api可以搞定; 

A页面 B页面嵌入的A页面改为http://a.com?data='xxx'

var data = location.search.split("=")[1];//data=。。。

    data = decodeURI(data);

    console.log('---来自父组件的值', data);

如果实现双向传值, 可以用代理的方式

代码如下:A页面http://localhost:8082

var data = location.search.split("=")[1];//data=。。。

      //如果有中文

      data = decodeURI(data);

      //使用window.localStorage存值,主页面可以调用事件获取该值,也可以用其他办法。

      // window.localStorage.setItem("data",data);

      console.log('孩子, 你带了什么给爸爸', data);

    window.onload = function(){

                var mainValue = "这是父页面的值";

                /*

                * 2.传值给跨域的iframe

                *  首先建立代理

                */

                var proxyOther = document.createElement('iframe'); 

                proxyOther.name = 'proxyOtherDomain';         

                proxyOther.style.display = 'none'; 

                document.body.appendChild(proxyOther);

                //这一步是关键,当需要传其他值时可以改变这个src

                proxyOther.src = 'http://localhost:8081/index.html?data='+mainValue; 

    }

B页面http://localhost:8081

var data = location.search.split("=")[1];//data=。。。

      //如果有中文

  data = decodeURI(data);

  console.log('---来自父组件的值', data);

window.onload = function() {

              var otherValue = "这是子页面的值";

                //首先建立代理

                var proxyMain = document.createElement('iframe'); 

                proxyMain.name = 'proxyMain';         

                proxyMain.style.display = 'none'; 

                document.body.appendChild(proxyMain);

                /*

                * 1.传值

                *  值可能是经过处理动态生成的,所以用setTimeout模拟一下

                */

                // setTimeout(function(){

                    proxyMain.src = 'http://localhost:8082/index.html?data='+otherValue; 

                // },2000);

                /*

                * 2.获取父页面传来的值

                */

                window.onstorage = function(){

                    var data = window.localStorage.getItem("data");

                    alert(data);

                    window.localStorage.clear();

                }

                // 也可以直接获取

                setTimeout(function(){

                    console.log(window.parent.proxyOtherDomain.data)

                },3000);

    }

3.使用window.name+iframe

代码如下: A页面:http://localhost:8081

// 加载跨域页面

    var iframe = document.createElement('iframe');

    iframe.src = "http://localhost:8082/#/home";

    let count = 0;

    // onload事件会触发2次,第1次加载跨域页,并留存数据于window.name

    iframe.onload = function() {

      // 第1次onload(跨域页)成功后,切换到同域代理页面

        console.log('-----', count);

      if(count === 0) {

        console.log('-----');

        iframe.contentWindow.location = 'http://localhost:8081/proxyOtherDomain.html';

        count = 1;

      } else {

        console.log(iframe.contentWindow.name);

      } 

    };

    document.body.appendChild(iframe);

B页面:http://localhost:8082

var data ={

name:"fangdown",

age:30

}

window.name =JSON.stringify(data);

这个我测试的时候是获取到iframe里面的window.name, 原理是, 在打开iframe的时候, 巧妙的利用了iframe.src和iframe.contentWindow.location, 拿到了window.name.


后续, 采用了第一种方式之后, 调试的时候, 惊喜的发现, 他网站的session, 放到我页面session上面, 竟然是可以发出请求的, 原来token本来就是通的, 那就采用把token传过来的方式来解决这个免密登陆的问题


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343