背景

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

为什么会跨域

为了保证用户信息的安全,95年的时候Netscape公司引进了同源策略,里面的同源指的是三个相同:协议、域名、端口。
违反了同源策略就会出现跨域问题,主要表现为以下三方面:

  • 无法读取cookie、localStorage、indexDB
  • DOM无法获得
  • ajax请求无法发送

场景

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

解决办法

设置domain

document.domain作用是获取/设置当前文档的原始域部分,同源策略会判断两个文档的原始域是否相同来判断是否跨域。这意味着只要把这个值设置成一样就可以解决跨域问题了。
在此我将domain设置为一级域名的值,a页面url为a.demo.com,a页面中iframe引用的b页面url为b.demo.com,具体设置为

document.domain = 'demo.com'

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

// a页面
window.toggleFullScreen = () => {
// do something
}

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

// b页面
window.parent.toggleFullScreen()

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

使用中间页面

我们还可以使用一个与a页面同域名但不同路由的c页面作为中间页面,b页面加载c页面,c页面调用a页面的方法,从而实现b页面调用a页面的方法。具体操作如下:
在a页面的node层新开一个路由,此路由加载一个c页面作为中间页面,c页面的url为a.demo.com/c。c页面只是一个简单的html页面,在window的onload事件上调用了a页面的方法。

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title></title>

</head>

<body>

    <script>

        window.onload = function () {

            parent.parent.toggleFullScreen();

        }

    </script>

</body>

</html>

由于c页面和a页面是符合同源策略的,所以可以避开跨域问题,执行全屏的方法。

postmessage

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

// b页面

parent.postMessage(

    value,

    "http://a.demo.com"

);

// a页面

window.addEventListener("message"function( event ) {

    if (event.origin !== 'http://b.demo.com'return;

    toggleFullScreen()

 });

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

总结

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

具体代码

在父、子页面中引用 communication.js,使用示例见(注意修改iframe-cross-domain-outer中嵌套的ifarme地址):iframe-cross-domain.rar

子页面发送消息

1

2

3

4

5

6

7

8

9

10

11

// 创建实例并初始化

var communication = new Communication(window.parent);

communication.init();

// put发送数据

communication.put(msg);

// get发送数据,使用回调函数接收返回值

communication.get(msg, function (data, event) {

   console.dir(data);

});

父页面接收消息

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

// 创建实例并初始化

var otherWindow = document.getElementById('idIframe').contentWindow;

var communication = new Communication(otherWindow);

communication.init();

 //接收put发送的的数据

communication.receiverAction = function (data, event) {

   console.dir(data);

}

// 接收get发送的数据,并且返回数据给调用方

communication.providerAction = function (data, event) {

    console.dir(data)

    return '测试返回'

}

iframe跨域的几种常用方法相关推荐

  1. 解决跨域的8种最常用方法(附终极通用大招)

    目录 引言 一.JSONP 跨域 二. iframe跨域 2.1 window.name + iframe跨域 2.2 location.hash + iframe跨域 2.3 document.do ...

  2. php 跨域读php_php跨域的几种方式

    PHP实现跨域的几种形式 1.JSONP(JSON with padding)原理 利用html里面script标签可以加载其他域下的js这一特性,使用script src的形式来获取其他域下的数据, ...

  3. 前端处理跨域的几种方式

    什么是跨域? 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的. 广义的跨域: 1.资源跳转:A链接.重定向.表单提交 2.资源嵌入: <link>.<scr ...

  4. iframe跨域通信的通用解决方案-第二弹!(终极解决方案)

    一年前,我发过一篇关于跨文档通信方案的文章<iframe跨域通信的通用解决方案>,提供了一种基于创建iframe与轮询window.name的方案. 一年后,很高兴地带来彻底改造的新版本. ...

  5. 【华为云技术分享】详解浏览器跨域的几种方法

    1前言 2背景知识介绍 2.1同源政策 2.2为什么要有跨域限制 3浏览器跨域的解决方案 3.1 CORS标准 3.2 CORS跨域判定的总体流程 3.3简单请求 3.4非简单请求 3.5 CORS相 ...

  6. 怎样获取不同域名的ifram的html,AJAX | iframe跨域的实现方法

    iframe跨域 HTML5学堂:本文当中我们介绍了跨域的基本知识,讲解到了跨域的相关种类,并讲解了解决跨域中的一种方法--如何使用iframe跨域.讲解了iframe跨域的基本原理与流程,并配以实战 ...

  7. 前端解决跨域的九种方法

    什么是跨域? 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的. 广义的跨域: 1.资源跳转:A链接.重定向.表单提交 2.资源嵌入: <link>.<scr ...

  8. 利用iframe跨域请求

    跨域是系统与系统之间信息交流的一种方式,为了获取另外一个地方的信息,经常会出现跨域,总结一下利用iframe跨域进行请求,网上关于跨域的信息很多,只做一下备忘 <!DOCTYPE html> ...

  9. 利用代理页面解决html iframe跨域访问网站问题

    原文:利用代理页面解决html iframe跨域访问网站问题 源代码下载地址: http://www.zuidaima.com/share/1854884509142016.htm 在做项目的时候遇到 ...

最新文章

  1. AI 行业寒冬犹在:融资规模不足巅峰时期一半,上市潮将伴随倒闭潮
  2. python中国余数定理_Python实现的中国剩余定理算法示例
  3. 抖音小程序微信小程序五角星型评分插件自定义分数组件
  4. CSDN内容颜色、位置以及图片大小改变
  5. 洛谷P1040-加分二叉树-dp+二叉树
  6. java点击按钮结线程_多线程的Java应用程序在调试工具Netbeans中单击“停止”按钮时输出一个奇怪的结果...
  7. 链家大数据多维分析引擎实践
  8. php表格位于页面中央,怎么为表格所在的页面添加编辑限制保护
  9. 【Kafka】Kafka Record for partition topic at offset xx is invalid, cause: Record corrupt
  10. Google 要进军游戏行业了?!
  11. Tomcat下work文件夹的作用
  12. LinkedIn第三方登录(JavaScript SDK)
  13. 代码调试全指南-自然语言处理-基于预训练模型的方法,车万翔
  14. 大内密探HMM(转)
  15. 一个比较稳定的PLC通讯模块设计
  16. 少儿编程微课程7:星际飞行单机版
  17. 推荐,Java Emoji Converter(Emoji表情转换工具)
  18. Springboot 搭建oss文件上传服务器
  19. 实用的费曼学习法 | 一些思考
  20. 【亚马逊运营】有关滞销库存的处理方法之站内清库存法!

热门文章

  1. Codeforces Round #659 (Div. 2) 题解
  2. 王者荣耀闪退服务器维护,王者荣耀:玩家游戏出现闪退,被禁赛128小时,一封邮件当场崩溃...
  3. 开源项目-蘑菇博客搭建
  4. java查看cpu核数以及jvm内存
  5. Object类九大方法之finalize方法
  6. SWUST OJ#1099(希尔排序算法实现)
  7. golang之RPC学习
  8. 重型自卸汽车设计(转向系及前桥设计)(论文+CAD图纸+开题报告+翻译……)
  9. subprocess.CalledProcessError: Command ‘[‘/home/***/anaconda3/envs/***/bin/python‘, ‘-u‘, ‘pretra
  10. 音质好的蓝牙耳机有哪些?音质最好的蓝牙耳机排行