美文网首页前端
iframe跨域通讯解决方案

iframe跨域通讯解决方案

作者: ll_夏 | 来源:发表于2020-06-06 17:39 被阅读0次

需求: 网站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传过来的方式来解决这个免密登陆的问题

相关文章

  • Web前后端跨域问题处理

    跨域问题有前台跨域(iframe间)和后台跨域。 前台跨域的解决方案可以采用跨域文档通讯(Cross domain...

  • iframe跨域通讯方式

    index iframe跨域通讯方式 __veblen iframe通讯分为两种情况,一个是同域下通讯,另一个是跨...

  • 前端如何解决常见跨域问题

    跨域解决方案 1、 通过jsonp跨域 2、 document.domain + iframe跨域 3、 loca...

  • iframe跨域通讯解决方案

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

  • Spring Boot使用CORS解决跨域问题

    一、跨域问题描述 Web开发经常会遇到跨域问题,解决方案有:jsonp,iframe,CORS等等。CORS 与 ...

  • 跨域的解决方案

    跨域的解决方案script,img,link,iframe,不存在跨域请求限制。1、JSONP, 客户端向服务器发...

  • iframe页面相互调用方法

    关键词:iframe,跨域,vue最近的项目中嵌入了外部的iframe,想跨域调用自己页面的方法,点击iframe...

  • spring boot CORS 支持

    一、Web 开发经常会遇到跨域问题,解决方案有:jsonp,iframe,CORS 等等 CORS 与 JSONP...

  • Iframe高度自适应

    1. 同域iframe高度自适应 2. 跨域iframe高度自适应

  • PHP跨域问题

    使用iframe方式实现局部刷新,但是iframe不支持跨域 通过script方式,src属性可以实现跨域,但只能...

网友评论

    本文标题:iframe跨域通讯解决方案

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