关于iframe跨域实践
提要
项目中与到iframe子页面中需要通过top获取在父页面中的全局变量的需求,由于App部署的缘故,导致父页面和iframe子页面分别在不同的端口下,导致iframe跨域现象,通过查阅资料进行问题解决。
浏览器有一个同源策略,第一种限制就是不能通过ajax的方法去请求不同源的文档。第二种限制是不能浏览器中不同域的框架之间是不能进行js的交互操作的。
不过有一点,不同框架之间(父子框架和同辈框架),是能够获取到彼此的window对象的,但是却不能获取到window对象的属性和方法(html5中的的postMessage方法是一个例外,还有些浏览器比如ie6也可以使用top、parent等少数几个属性),总之,你可以当做是只能获取到一个几乎无用的window对象。比如,有一个页面,它的地址是http://wwww.example.com/a.html, 在这个页面里边有一个iframe,它的src是http://example.com/b.html,很显然,这个页面与它里边的iframe框架是不同域的,所以我们是无法通过在页面中书协js代码来获取iframe中的东西的,同样iframe中的内容也无法直接获取到a.html中的内容。
实践
根据博客中介绍的几种方式进行实践:
通过修改document.domain来跨子域
子域中无法获取父域的数据的时候就可以利用document.domain都设置成相同的域名就可以完成。但是要注意的是,document.domain的设置是有限制的,我们把document.domain设置成自身或者更高一级的父域,且主域必须相同。例如:a.b.example.com中某个文档的document.domaiin可以设成a.b.example.com、b.example.com、example.com中的任意一个,但是不可以设成c.a.b.example.com,因为这是当前作用于的子域,也不能设成baidu.com,因为主域已经不相同了。
这种方式用来获取端口不同的跨域处理起来是很方便的:
//父域的运行环境是http://localhost:8087/
//同样在部署在同一台服务器上的不同端口的应用也是适用的 <iframe src="http://localhost:8086/" id="iframepage" width="100%" height="100%" frameborder="0" scrolling="yes" onLoad="getData"></iframe> <script>
window.parentDate = {
"name": "hello world!",
"age": 18
}
/**
* 使用document.domain解决iframe父子模块跨域的问题
*/
let parentDomain = window.location.hostname;
console.log("domain",parentDomain); //localhost
document.domain = parentDomain;
</script>
//子域的运行环境是http://localhost:8086/ <script>
/**
* 使用document.domain解决iframe父子模块跨域的问题
*/
console.log(document.domain); //localhost
let childDomain = document.domain;
document.domain = childDomain;
let parentDate = top.parentDate;
console.log("从父域获取到的数据",parentDate);
// 此处打印数据为
// {
// "name": "hello world!",
// "age": 18
// }
</script>
到这里就能够把主域的数据传递给子域了。同样也可以把子域的数据传递子域:
//子域的获取到top之后给top上添加属性 <script>
let childDomain = document.domain;
document.domain = childDomain; top.childData = { //获取到top之后给top添加属性
"name": "你好世界!",
"age": 26
}
</script>
//父域在iframe加载完成之后就可以获取到子域添加的属性 <iframe src="http://localhost:8086/" id="iframepage" width="100%" height="100%" frameborder="0" scrolling="yes" onLoad="getData"></iframe> <script>
getData(){
console.log("子域传递给父域的数据",top.childData);
// 此处打印数据
// {
// "name": "你好世界!",
// "age": 26
// }
}
</script>
这样就可以完成父子组件之间的通讯了。
不过如果你想在http://www.example.com/a.html页面中通过ajax直接请求http://example.com/b.html页面,即使你设置了相同的document.domain也还是不行的,所以修改document.domain的方法只适用于不同子域的框架间的交互。
使用HTML5中新引入的window.postMessage方法来跨域传递数据
window.postMessage(message, targetOrgin)方法是html5新引进的特性,可以使用它来想其他的window对象发送消息,无论这个window对象是属于同源或者不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。
调用postMessage方法的window对象是指要接受消息的哪一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrgin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符*。
需要接收消息的window对象,可是通过监听自身的message时间来获取传过来的消息,消息内容存储在该事件对象的data属性中。
上面所有的向其他window对象发送消息,其中就是指一个页面有几个框架的那种情况,因为每一个框架都有一个window对象。在讨论第二种方法的时候,我们说过,不同域的框架间是可以获取到对象的window对象的,而且也可以使用window.postMessage这个方法。
//父域的运行环境是http://localhost:8087/ <iframe src="http://127.0.0.1:8086/" id="iframepage" width="100%" height="100%" frameborder="0" scrolling="yes" onLoad="getData"></iframe> <script>
getData(){
let iframe = document.getElementById('iframepage');
let win = iframe.contentWindow;
win.postMessage(JSON.stringify(parentDate),"*");
}
</script>
//子域的运行环境是http://127.0.0.1:8086/ /**
* 使用postMessage解决iframe父子模块跨域的问题
*/
window.onmessage = function(e){
e = e || event;
console.log("从父域获取到的数据",JSON.parse(e.data));
// 此处打印的数据为
// {
// "name": "hello world!",
// "age": 18
// }
}
这样在任何一个域内都可以获取到从父域传递的数据。通过postMessage来跨域传递数据还是比较直观和方便的,但是缺点是IE6、IE7不支持,至于能不能用可以在 Can I use上进行验证。目前看到的是IE11是部分支持,不过刚才的方法在IE11上验证是能够正常执行的。
关于iframe跨域实践的更多相关文章
- 利用window.name+iframe跨域获取数据详解
详解 前文提到用jsonp的方式来跨域获取数据,本文为大家介绍下如何利用window.name+iframe跨域获取数据. 首先我们要简单了解下window.name和iframe的相关知识.ifra ...
- iframe 跨域问题解决方案 利用window.name+iframe跨域获取数据详解
详解 前文提到用jsonp的方式来跨域获取数据,本文为大家介绍下如何利用window.name+iframe跨域获取数据. 首先我们要简单了解下window.name和iframe的相关知识.ifra ...
- JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)
这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...
- javascript跨域、iframe跨域访问
1.window 对象 浏览器会在其打开一个 HTML 文档时创建一个对应的 window 对象.但是,如果一个文档定义了一个或多个框架(即,包含一个或多个 frame 或 iframe 标签),浏览 ...
- iframe跨域cookie问题
今天在项目里面遇到了iframe跨域不能写cookie的问题.应用场景是这样的:有A和B两个业务,A要通过iframe的方式嵌入B,但是在ie下A不能通过写cookie的方式记录信息,在firefox ...
- iframe跨域访问
js跨域是个讨论很多的话题.iframe跨域访问也被研究的很透了. 一般分两种情况: 一. 是同主域下面,不同子域之间的跨域: 同主域,不同子域跨域,设置相同的document.domian就可以解决 ...
- 利用location.hash+iframe跨域获取数据详解
前言 如果看懂了前文利用window.name+iframe跨域获取数据,那么此文也就很好理解了.一样都是动态插入一个iframe,然后把iframe的src指向服务端地址,而服务端同样都是输出一段j ...
- CP="CAO PSA OUR" 用P3P header解决iframe跨域访问cookie
1.IE浏览器iframe跨域丢失Session问题 在开发中,我们经常会遇到使用Frame来工作,而且有时是为了跟其他网站集成,应用到多域的情况下,而Iframe是不能保存Session的因此,网上 ...
- 在IE浏览器中iframe跨域访问cookie/session丢失的解决办法
单点登录需要在需要进入的子系统B中添加一个类,用于接收A系统传过来的参数: @Action(value = "outerLogin", results = { @Result(na ...
随机推荐
- Xamarin.Android 使用 SimpleAdapter 打造 ListView 万能适配器
第一步:创建 layout1.axml 来展示列表详细内容 <?xml version="1.0" encoding="utf-8"?> <L ...
- mysql 开发进阶篇系列 10 锁问题 (相同索引键值或同一行或间隙锁的冲突)
1.使用相同索引键值的冲突 由于mysql 的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但如果是使用相同的索引键,是会出现锁冲突的.设计时要注意 例如:city表city_ ...
- Spring boot @EnableScheduling 和 @Scheduled 注解使用例子
前言 Spring Boot提供了@EnableScheduling和@Scheduled注解,用于支持定时任务的执行,那么接下来就让我们学习下如何使用吧: 假设我们需要每隔10秒执行一个任务,那么我 ...
- BFC是个什么概念?
在布局中一般就三种定位方式:普通流.浮动.绝对定位. BFC,译过来叫作“块级格式化上下文”,听起来贼高大上,它属于普通流的一种.通俗一点来讲,可以把 BFC 理解为一个封闭的大箱子,箱子内部的元素无 ...
- mysql的"双1设置"-数据安全的关键参数(案例分享)
mysql的"双1验证"指的是innodb_flush_log_at_trx_commit和sync_binlog两个参数设置,这两个是是控制MySQL 磁盘写入策略以及数据安全性 ...
- mysql年初至今聚合
年初至今聚合和滑动聚合类似,不同的地方仅在于统计的仅为当前一年的聚合.唯一的区别体现在下限的开始位置上.在年初至今的问题中,下限为该年的第一天,而滑动聚合的下限为N个月的第一天.因此,年初至今的问题的 ...
- SpringBoot(9) SpringBoot整合Mybaties
一.近几年常用的访问数据库的方式和优缺点 1.原始java访问数据库 开发流程麻烦 <1>注册驱动/加载驱动 Class.forName("com.mysql.jdbc.Driv ...
- Nacos系列:基于Nacos的配置中心
前言 在看正文之前,我想请你回顾一下自己待过的公司都是怎么管理配置的,我想应该会有以下几种方式: 1.硬编码 没有什么配置不配置的,直接写在代码里面,比如使用常量类 优势:对开发友好,开发清楚地知道代 ...
- haproxy(8):haproxy代理MySQL要考虑的问题
HaProxy系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.html haproxy可以通过 TCP协议 来代理MySQL.但是两个问题必须考虑: ...
- linux 常用命令集合-命令导图
这几天画了几张导图,自己熟悉命令,并记录总结一下,还有很多没写上去,在慢慢完善把. 1.帮助命令 2.文件搜索命令 3.用户管理 4.权限管理 5.文件处理类 6.压缩解压 7.网络配置类 8.关机重 ...