iframe笔记

—— 全文摘自Web前端之iframe详解_someby的博客-CSDN博客_iframe详解 

实现一个页面数据编辑的功能的时候就需要使用一个iframe内联框架 

iframe常用属性:

1.frameborder:是否显示边框,1(yes),0(no)

2.height:框架作为一个普通元素的高度,建议在使用css设置。

3.width:框架作为一个普通元素的宽度,建议使用css设置。

4.name:框架的名称,window.frames[name]时专用的属性。

5.scrolling:框架的是否滚动。yes,no,auto。

6.src:内框架的地址,可以是页面地址,也可以是图片的地址。

7.srcdoc:用来替代原来HTML body里面的内容。但是IE不支持。

8.sandbox:对iframe进行一些列限制,IE10+支持。

 获取iframe里的内容

iframe.contentWindow,获取iframe的window对象

iframe.contentDocument,获取iframe的getElement系列对象

结合Name属性,通过window提供的iframe获取,window.frames['ifr1'].window,它返回的就是window对象。即window.frames['ifr1']===window

在iframe中获取父级内容

window.parent 获取上一级的window对象,如果还是iframe则是该iframe的window对象

window.top 获取最顶级容器的window对象,即,就是你打开页面的文档

window.self 返回自身window的引用。可以理解 window===window.self

自适应iframe之蜜汁广告

广告是与原文无关的,如果是在某个div下嵌套,会造成网页布局的紊乱,而且,这样势必需要引入额外的css和js文件,极大的降低了网页的安全性。但是使用iframe,里面的内容能够被top window完全控制,而且,主页的样式不会入侵iframe里面的样式。但是,默认情况下,iframe是不适合做展示信息的,所以我们需要对其进行decorate。

自适应iframe

默认情况下,iframe会自带滚动条,不会全屏。如果你想自适应iframe的话:第一步:去掉滚动条

<iframe src="./iframe1.html" id="iframe1" scrolling="no"> </iframe>

第二步,设置iframe的高为body的高

1. var iwindow = iframe.contentwindow;

2. var idoc = iwindow.document;

3. iframe.height = idoc.body.offsetHeight; 

另外,还可以添加其他的装饰属性:

属性效果
allowtransparency

true or false

是否允许iframe设置为透明,默认为false

allowfullscreen

true or false

是否允许iframe全屏,默认为false

iframe安全性探索

防嵌套网页

因为iframe享有click的最优先权,当有人在伪造的主页进行点击的话,如果点在iframe上,则会默认是在操作iframe的页面。所以,为了防止网站被钓鱼,可以使用window.top来防止你的网页被iframe

//iframe2.html

if(window != window.top) {
     
     window.top.location.href = correctURL;

}

这段代码的主要用途是限定你的网页不能嵌套在任意网页内。如果你想引用同域的框架的话,可以判断域名。

if (top.location.host != window.location.host) {

   top.location.href = window.location.href;

}

如果你网页不同域名的话,上述就会报错。

所以,这里可以使用try...catch...进行错误捕获。如果发生错误,则说明不同域,表示你的页面被盗用了。可能有些浏览器这样写是不会报错的,所以需要降级处理。

这时候再进行跳转即可。

try {

     top.location.hostname;  // 检测是否出错

     // 如果没有出错,则降级处理

     if (top.location.hostname != window.location.hostname) {

          top.location.href = window.location.href;

      }

}

catch(e) {

      top.location.href = window.location.href;

}

上面的代码只是在浏览器端,对iframe页面的权限做出相关的设置,我们还可以在服务器上,对使用iframe的权限进行设置。

以后网页安全防护的主流是Content Security Policy,他可以对iframe进行限制

CSP之页面防护

需要在服务器端设置好相关的Header。CSP的作用,他能极大的防止你的页面被XSS攻击,而且可以制定js,css,img等相关资源的origin,防止被恶意注入。不过他目前只支持Edge12+以及IE10+。

在前端,我们可以观察Response Header里是否有这样的一个Header:

Content-Security-Policy:default-src 'self'  // 默认资源路径就是同域的

这就表明,你的网页时启用CSP的。

这里和iframe有一点瓜葛的时child-src和sandbox。

children-src就是用来指定iframe的有效加载路径;而,sandbox其实就和iframe的sandbox一样他可以规定来源能够带有什么权限。

来个demo:

Content-Security-Policy:child-src 'selt'  http://example.com;  sandbox  allow-forms  allow-same-originn

此时,iframe的src就只能加载同域和example.com页面。使用CSP能够很好的防止XSS攻击,原理就是CSP会默认escape掉内联样式和脚本,以及eval执行。但是,你可以使用srcipt-src进行降低限制。

Content-Security-Policy:script-src  'unsafe-inline'

当我们iframe别人的页面时,我们需要对其进行安全设限。

sandbox 

sandbox就是用来给指定iframe设置一个沙盒模型限制iframe的更多权限,

sandbox时h5的一个新属性,IE10+支持,

启用方式就是使用sandbox属性:

<iframe sandbox src="..."> </iframe> 

这样会对iframe页面进行一系列的限制:

1. script脚本不能执行

2. 不能发送ajax请求

3. 不能使用本地存储,即localStorage,cookie等

4. 不能创建新的弹窗和window

5. 不能发送表单

6. 不能加载额外插件比如flash等

上面的限制有点过分了 ,不过,你可以放宽一点权限。在sandbox里面进行一些简单设置

<iframe sandbox="allow-same-origin"  src="...."> </iframe>

常用的配置项有:   

配置效果
allow-forms允许进行提交表单
allow-scripts运行执行脚本
allow-same-origin允许同域请求,比如Ajax,storage
allow-top-navigation允许iframe能够主导window.top进行页面跳转
allow-popups允许iframe中弹出新窗口,比如,window.open,target="_blank"
allow-pointer-lock在iframe中可以锁定鼠标,主要和鼠标锁定有关

 可以通过在sandbox里,添加允许进行的权限。

<iframe sandbox="allow-forms  allow-same-origin  allow-scripts"  src="..."> </iframe>

 这样,就可以保证js脚本的执行,但是禁止iframe里的javascript执行top.location = self.location。

但是,iframe的安全问题还时有很多的,比如location劫持,Refers检查。

解决iframe跨域

iframe就是一个隔离沙盒,相当于我们在一个页面内可以操控很多标签页一样。

我们需要明确什么是跨域。

浏览器判断你跨没跨域,主要根据两个点。一个是你网页的协议(protocol),一个就是你的host是否相同,即,就是url的首部:

window.location.protocol  + window.location.host

需要强调的是,url首部必须一样,比如:二级域名或者IP地址不一样,都算是跨域。

// 域名和域名对应ip,跨域

http://www.a.com/a.js

http://70.32.92.74/b.js

// 统一域名,不同二级域名。跨域

http://www.a.com/a.js

http://a.com/b.js

对于第二种方式的跨域(主域相同而子域不同),可以使用iframe进行解决。

在两个不同子域下(某一方使用iframe嵌套在另一方),

即:

http://www.foo.com/a.html和http://script.foo.com/b.html

两个文件中分别加上document.domain = 'foo.com',指定相同的主域,然后,两个文档就可以进行交互。


//b.html是以iframe的形式嵌套在a.html中
//www.foo.com上的a.html
document.domain = 'foo.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.foo.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    // 在这里操纵b.html
    alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};
//script.foo.com上的b.html

默认情况下document.domain是指window.location.hostname.你可以手动更改,但是最多只能设置为主域名。通常,主域名就是不带www的hostname,比如:foo.com, baidu.com。如果,带上www或者其他的前缀,就是二级域名或者多级域名。通过上述设置,相同的domain之后,就可以进行同域的相关操作。另外还可以使用iframe和location.hash,但这个技术out了。 

H5的CDM跨域与iframe 

如果你设置的iframe的域名和你top window的域名完全不同。则可以使用CDM(cross  document  messaging)进行跨域消息的传递。该API的兼容性较好 IE8+都支持。

推送消息:使用postmessage方法

接受消息:监听message事件

postmessage

该方法挂载到window对象上,即,使用window.postmessage()调用。

该方法接受两个参数:postMessage(message,targetOrigin):

message:就是传递给iframe的内容,通常是string,如果你想传object对象也可以。不过使用前请参考这一句话:

Objects  listed  in  transfer  are  transferred,  not  just  cloned,  meaning  that  they  are  no  longer  usable  on  the  sending  side.

意思就是,希望亲爱的不要直接传Object。如果有条件,可以使用JSON.stringify进行转化。这样保证不会出bug。

targetOrigin:接收你传递消息的域名,可以设置绝对路径,也可以设置"" 或者 "/"。 表示任意域名都行, "/" 表示只能传递同域域名。

来个栗子:


 <iframe src="http://tuhao.com" name="sendMessage"></iframe>
//当前脚本
let ifr = window.frames['sendMessage'];
   //使用iframe的window向iframe发送message。
ifr.postmessage('give u a message', "http://tuhao.com");
//tuhao.com的脚本
window.addEventListener('message', receiver, false);
function receiver(e) {
    if (e.origin == 'http://tuhao.com') {
        if (e.data == 'give u a message') {
            e.source.postMessage('received', e.origin);  //向原网页返回信息
        } else {
            alert(e.data);
        }
    }

当targetOrigin接受到message消息之后,会触发message事件。message提供的event对象上有3个重要的属性,data,origin,source.

data:  postMessage传递进来的值

origin:发送消息的文档所在的域

source:发送消息文档的window对象的代理,如果是来自同一个域,则该对象就是

window,可以使用其所有方法,如果是不同的域,则window只能调用postMessage()方法返

回信息。

iframe的使用

1.通过iframe实现跨域(就是嵌入其他页面的)

2.通过iframe解决Ajax的前进后退问题

3.通过iframe实现上传

(Easyui中form组件就是用的iframe,实现表单提交,可以提交上传)

4.对低版本html不支持 iframe 元素的。

(我们可以把需要的文本放置在 <iframe> 和 </iframe> 之间,这样就可以应对浏览器了。)

<iframe width=420 height=330 frameborder=0 scrolling=auto src="URL"> </iframe>

摘录感悟

因为在工作中接手之前写的代码,里面操纵数据是使用iframe,之前只听说过,没有遇到过。今天摘抄完也是稍有理解,摘抄的目的其一是了解和学习iframe,其二是学习优秀的程序员的代码思路,知识拆解。希望自己也慢慢养成良好的习惯,不断学习总结,变得越来越厉害

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值