Iframe简单探索以及Iframe跨域处理

探索Iframe

本文目的:html

  • Iframe简单使用算法

  • Iframe跨域json

  • Iframe常见问题segmentfault


一.Iframe基本Dom以及经常使用属性和经常使用事件

1.DOM:

<iframe class="iframe" style="height: 100%;width: 100%;border: 0;"  id="Yiframe" name="Yiframe" src='http://localhost:2255/67iframe-2.html' ></iframe>

2.经常使用属性:

和平时使用的DOM标签相似,样式之类的仍是建议用class吧,统一块儿来方便管理。跨域

更多属性看:http://www.runoob.com/tags/ta...数组

3.经常使用事件:

<iframe> 标签支持 HTML 的事件属性浏览器

通常用这个就够了安全

onload:当文档加载时运行脚本app

document.querySelector('#Yiframe').onload = function(event){
            console.log('onload',event);
        }

二.JS动态新增并插入Iframe

和平时新增DOM标签同样便可。框架

var iframe = document.createElement('iframe');
     iframe.src = url;
     iframe.id = "Yiframe";
     iframe.style="height: 100%;width: 100%;border: 0;";
     $('.content').append(iframe);

三.iframe与父页面互动

1.注意事项

(1). 必须是在二者同域的状况下才能进行数据交互。

(2). 中间不管嵌套几回iframe,只要其中一个iframe与上级或者上上级同域,二者以前就能进行相互调用

2.实现方案(同域)

(1).父页面获取子页面

document.querySelector('#XXXX').contentWindow

window.frames[x]

能够获取到iframe内的window对象,包括iframe内自行声明的全局方法等。

window.frames注意事项:
  • 该属性返回窗口中全部命名的框架(<iframe>)。

  • 直接打印window.frames不是数组对象。

  • frames.length 来获取框架的数量。

  • 能够经过window.frames[数字]直接获取iframe内的window对象。

(2).子页面获取父页面

window.parent

能够获取到父页面的window对象,包括父页面内自行声明的全局方法等。

3.跨域(未跨主域)

(1).尝试。

打印 document.querySelector('#XXXX').contentWindow 和 window.parent 能够看到里面的属性和方法(第一层/第二层)。

但关键数据和方法会被和谐。

image

(2).修改document.domain实现跨域通讯

网上搜到这个方法,但本身尝试的时候总会报错:

VM301:1 Uncaught DOMException: Failed to set the 'domain' property on 'Document': 'baidu.com' is not a suffix of 'corp.dinghuo123.com'.
    at <anonymous>:1:17

由于同源安全政策不能直接修改。

首先补充一个知识点,而后再讲解怎么使用。

知识点:

一级域名 有的人叫根域名,如:dinghuo123.com、baidu.com、xx.com.cn、xx.cn.net 等等。

二级域名 是指增长了一级,包括www。如:www.dinghuo123.com、corp.dinghuo123.com、agent.dinghuo123.com 等等。因此有人把www.dinghuo123.com叫一级域名这是错误的。

document.domain 能够修改 corp.dinghuo123.com、agent.dinghuo123.com 为同一个主域 dinghuo123.com,此时便可经过上面步骤三-2实现父子之间的通讯。

可是跨主域的时候就不能用这个方法了。

4.跨域(跨主域)

(1)方法

发送方:
otherWindow.postMessage(message, targetOrigin, [transfer]);

otherWindow

//其余窗口的一个引用,
//(1)好比iframe的contentWindow属性、
//(2)执行window.open返回的窗口对象、
//(3)或者是命名过或数值索引的window.frames。
//(4)父级parent.window对象

message

//将要发送到其余 window的数据。它将会被结构化克隆算法序列化。这意味着你能够不受什么限制的将数据对象安全的传送给目标窗口而无需本身序列化。
//PS我的以为如果对象尽可能仍是自行序列化吧避免出现什么奇怪的问题。

targetOrigin

//经过窗口的origin属性来指定哪些窗口能接收到消息事件,其值能够是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,若是目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者彻底匹配,消息才会被发送。这个机制用来控制消息能够发送到哪些窗口;例如,当用postMessage传送密码时,这个参数就显得尤其重要,必须保证它的值与这条包含密码的信息的预期接受者的orign属性彻底一致,来防止密码被恶意的第三方截获。若是你明确的知道消息应该发送到哪一个窗口,那么请始终提供一个有确切值的targetOrigin,而不是*。不提供确切的目标将致使数据泄露到任何对数据感兴趣的恶意站点。
//PS简单来讲就是*的话对方不管是什么URL都会触发onmessage回调,若是不是就会报错(图片见下方)


transfer //可选

//是一串和message 同时传递的 Transferable 对象. 这些对象的全部权将被转移给消息的接收方,而发送一方将再也不保有全部权。
//PS这个不是很懂,后面有时间研究。

targetOrigin报错图
图片描述

postMessage兼容性
图片描述

监听方:
window.onmessage = function(e){ console.log(e)}

e.source //能够得到父级window对象(必须是同域)
e.origin  //检查postMessage的发送页面的源。

(2)实践

父向子

//父:
document.querySelector('#xx').onclick = function(){
    window.frames[0].postMessage('testPost','*'); 
    //document.querySelector('#Yiframe').contentWindow.postMessage('testPost','*'); 也能够
}
//子:
window.onmessage =function(e){
    console.log('onmessage2',e,document.domain);
}

子向父

//子:
document.querySelector('#btn5').addEventListener('click',function(){
    parent.window.postMessage('testChildPost','*');
});

//父:
window.onmessage = function(e){ 
    console.log('onmessage父',e) 
}

两个窗口:

理论上把window对象浏览器存储下再用上面的方式就能实现。何尝试。

(3)安全问题

若是您不但愿从其余网站接收message,请不要为message事件添加任何事件侦听器。 这是一个彻底万无一失的方式来避免安全问题。

若是您确实但愿从其余网站接收message,请始终使用origin和source属性验证发件人的身份。 任何窗口(包括例如http://evil.example.com)均可以向任何其余窗口发送消息,而且您不能保证未知发件人不会发送恶意消息。 可是,验证身份后,您仍然应该始终验证接收到的消息的语法。 不然,您信任只发送受信任邮件的网站中的安全漏洞可能会在您的网站中打开跨网站脚本漏洞。

当您使用postMessage将数据发送到其余窗口时,始终指定精确的目标origin,而不是*。 恶意网站能够在您不知情的状况下更改窗口的位置,所以它能够拦截使用postMessage发送的数据。

四.路由变化以及前进后退。

  1. 控制台使用window.location.href会致使浏览器的url变化。

  2. 用户点击后退或者前进的时候,会根据以前的操做,彻底依次复现(变化浏览器url和iframe内部页面路由变化)

  3. window.history.go(xx) 和 window.history.back() ,不管在父页面仍是在子页面中,使用的效果和浏览器的前进后退是同样的。

  4. iframe中的页面使用window.location.href(和a标签)改变路由的时候不会引起浏览器url的变化,但会新增一条历史记录

  5. iframe每次重载,都会触发onload事件。

五.常见问题

  1. iframe内的路由变化,iframe的src值不会变!!!

  2. 要获取iframe内的当前url,用document.querySelector('#Yiframe').contentWindow.location.href;

  3. parent.window 在没有父级的时候 parent.window = window;

参考资料

SO JSON在线解析:http://www.sojson.com/blog/17...

浏览器同源政策: https://developer.mozilla.org...

postMessage:https://developer.mozilla.org...

相关文章
相关标签/搜索