• iframe的src可以引入任何源,但是二者如果想通信的话,必须是同源,如果是非同源,如何解决?


    iframe的src可以引入任何源,但是二者如果想通信的话,必须是同源。

    背景

    随着业务的发展,自然地会有一些公共的业务被抽离成为公共组件供各个项目使用。但是由于各个项目用到的技术栈都有所不同,所以这个公共组件就不能方便地被引用了。为解决这个问题,我们把这个组件写成了单独的页面挂到一个域名下,其他项目采用iframe或者webview的方式去加载这个页面,从而实现功能的简单复用。
    不过这过程中也产生了很多问题,比如通信跨域。以下我将会介绍我遇到的跨域问题以及一些解决方法。

    场景

    最近在做一个需求,需要用iframe引入一个别人封装好的类似视频播放器的东西。iframe里面有一个全屏的按钮,点击后需要页面让iframe全屏,由于受到同源策略的限制,iframe无法告诉页面全屏。

    解决方法
    1. 设置domain 该方法在mdn上已不推荐使用,而且已废弃

    document.domain 是 JavaScript 中的一个属性,用于设置或获取当前页面的域名。

    它的作用是允许在同一个域名下的不同子域之间进行跨域通信。默认情况下,不同子域之间的 JavaScript 代码是无法直接访问彼此的属性和方法的,这是出于安全考虑的限制。但是,如果将它们的 document.domain 设置为相同的值,就可以解除这个限制。

    使用方法很简单,只需要在 JavaScript 中设置 document.domain 属性为相同的值即可。例如:

    // 在父页面中设置 document.domain
    document.domain = "example.com";
    
    // 在子页面中也设置 document.domain
    document.domain = "example.com";
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这样,父页面和子页面就可以通过 JavaScript 代码进行跨域通信了。

    需要注意的是,为了使用 document.domain 进行跨域通信,域名必须满足以下条件:

    • 主域名相同
    • 端口号相同
    • 协议相同

    否则,浏览器将不允许使用 document.domain 进行跨域通信。

    设置完之后,在a页面的window上挂载使iframe全屏的方法

    // a页面
    window.toggleFullScreen = () => {
        // do something
    }
    
    • 1
    • 2
    • 3
    • 4

    在b页面上可以直接获取到a页面的window对象并直接调用

    // b页面
    window.parent.toggleFullScreen()
    
    • 1
    • 2

    但是这个值的设置也有一定限制,只能设置为当前文档的上一级域或者是跟该文档的URL的domain一致的值。如url为a.demo.com,那domain就只能设置为demo.com或者a.demo.com。因此,设置domain的方法只能用于解决主域相同而子域不同的情况。

    2. postmessage

    window.postMessage方法可以安全地实现跨源通信,写明目标窗口的协议、主机地址或端口就可以发信息给它。

    // b页面
    parent.postMessage(
        value,
        "http://a.demo.com"
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    // a页面
    window.addEventListener("message", function( event ) {
        if (event.origin !== 'http://b.demo.com') return;
        toggleFullScreen()
     });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    为了安全,收到信息后要检测下event.origin判断是否要收信息的窗口发过来的。

    总结

    通过以上的方法,我们就可以和iframe自由通信啦。

    参考:iframe跨域的几种常用方法:https://juejin.cn/post/6844903831973675015

  • 相关阅读:
    机器人课程教师面对的困境有哪些(补充)
    MySQL - 多表查询与案例详解
    AXI三种接口及DMA DDR XDMA介绍(应用于vivado中的ip调用)
    Linux——Xshell、Xftp实现Linux远程登录与应用
    【台前调度】使用指南:如何打开和关闭iPadOS 16台前调度
    【VMware/Linux】虚拟机根目录扩容
    Quartz之数据库存储(代码案例)
    scala/java redis的cluster模式 删除固定前缀的key
    天锐绿盾数据防泄密系统
    四元数的可视化
  • 原文地址:https://blog.csdn.net/yexudengzhidao/article/details/127443319