js innerHTML 的一些问题的解决方法


Posted in Javascript onJune 22, 2008

然而,你需要知道 innerHTML 有一些自身的问题: 

1、当 HTML 字符串包含一个标记为 defer 的 script 标签(<script defer>…</script>)时,如 innerHTML 属性处理不当,在 Internet Explorer 上会引起脚本注入攻击。 
2、设置 innerHTML 将会破坏现有的已注册了事件处理函数的 HTML 元素,会在某些浏览器上引起内存泄露的潜在危险。 

还有几个其他次要的缺点,也值得一提的: 

1、你不能得到刚刚创建的元素的引用,需要你手动添加代码才能取得那些引用(使用 DOM APIs)。 
2、你不能在所有浏览器的所有 HTML 元素上设置 innerHTML 属性(比如,Internet Explorer 不允许你在表格的行元素上设置innerHTML 属性)。 
我更关注与使用 innerHTML 属性相关的安全和内存问题。很显然,这不是新问题,已经有能人围绕这些中的某些问题想出了方法。 

       Douglas Crockford 写了一个 清除函数 ,该函数负责中止由于 HTML 元素注册事件处理函数引起的一些循环引用,并允许垃圾回收器(garbage collector)释放与这些 HTML 元素关联的内存。 

       从 HTML 字符串中移除 script 标签并不像看上去那么容易。一个正则表达式可以达到预期效果,虽然很难知道是否覆盖了所有的可能性。这里是我的解决方案: 
/<script[^>]*>[\S\s]*?<\/script[^>]*>/ig
现在,让我们将这两种技术结合在到一个单独的 setInnerHTML 函数中,并将 setInnerHTML 函数绑定到 YUI 的 YAHOO.util.Dom 上:
YAHOO.util.Dom.setInnerHTML = function (el, html) {
    el = YAHOO.util.Dom.get(el);
    if (!el || typeof html !== 'string') {
        return null;
    } 
    // 中止循环引用
    (function (o) {

        var a = o.attributes, i, l, n, c;
        if (a) {
            l = a.length;
            for (i = 0; i < l; i += 1) {
                n = a[i].name;
                if (typeof o[n] === 'function') {
                    o[n] = null;
                }
            }
        }

        a = o.childNodes;

        if (a) {
            l = a.length;
            for (i = 0; i < l; i += 1) {
                c = o.childNodes[i];

                // 清除子节点
                arguments.callee(c);

                // 移除所有通过YUI的addListener注册到元素上所有监听程序
                YAHOO.util.Event.purgeElement(c);
            }
        }

    })(el);

    // 从HTML字符串中移除script,并设置innerHTML属性
    el.innerHTML = html.replace(/<script[^>]*>[\S\s]*?<\/script[^>]*>/ig, "");

    // 返回第一个子节点的引用
    return el.firstChild;
};

如果此函数还应有其他任何内容或者在正则表达式中遗漏了什么,请让我知道。 

       很明显,在网页上还有很多其他注入恶意代码的方法。setInnerHTML 函数仅能在所有 A-grade 浏览器上规格化 <script> 标签的执行行为。如果你准备注入不能信任的 HTML 代码,务必首先在服务器端过滤,已有许多库可以做到这点。

Javascript 相关文章推荐
js中将字符串转换成json的三种方式
Jan 12 Javascript
基于jQuery实现下拉框
Nov 24 Javascript
JavaScript使用Math.Min返回两个数中较小数的方法
Apr 06 Javascript
AngularJs Scope详解及示例代码
Sep 01 Javascript
Javascript中常见的逻辑题和解决方法
Sep 17 Javascript
微信小程序  modal弹框组件详解
Oct 27 Javascript
jQuery插件zTree实现获取当前选中节点在同级节点中序号的方法
Mar 08 Javascript
基于JavaScript定位当前的地理位置
Apr 11 Javascript
DVA框架统一处理所有页面的loading状态
Aug 25 Javascript
微信小程序实现顶部下拉菜单栏
Nov 04 Javascript
如何进行微信公众号开发的本地调试的方法
Jun 16 Javascript
微信小程序实现加入购物车滑动轨迹
Nov 18 Javascript
很酷的javascript loading效果代码
Jun 18 #Javascript
豆瓣网的jquery代码实例
Jun 15 #Javascript
JQuery实现自定义对话框的代码
Jun 15 #Javascript
javascript基本语法分析说明
Jun 15 #Javascript
javascript新手语法小结
Jun 15 #Javascript
JavaScript入门学习书籍推荐
Jun 12 #Javascript
asp.net和asp下ACCESS的参数化查询
Jun 11 #Javascript
You might like
Codeigniter框架的更新事务(transaction)BUG及解决方法
2014/07/25 PHP
PHP简单实现冒泡排序的方法
2016/12/26 PHP
PHP PDOStatement::getAttribute讲解
2019/02/01 PHP
javascript 数组排序函数
2009/08/20 Javascript
Fastest way to build an HTML string(拼装html字符串的最快方法)
2011/08/20 Javascript
Javascript弹出窗口的各种方法总结
2013/11/11 Javascript
脚本合并提升javascript性能示例
2014/02/24 Javascript
JS字符串拼接在ie中都报错的解决方法
2014/03/27 Javascript
整理AngularJS中的一些常用指令
2015/06/16 Javascript
JavaScript获取对象在页面中位置坐标的方法
2016/02/03 Javascript
AngularJS国际化详解及示例代码
2016/08/18 Javascript
AngularJS折叠菜单实现方法示例
2017/05/18 Javascript
Angular.js指令学习中一些重要属性的用法教程
2017/05/24 Javascript
JS原生带缩略图的图片切换效果
2018/10/10 Javascript
详解微信图片防盗链“此图片来自微信公众平台 未经允许不得引用”的解决方案
2019/04/04 Javascript
基于vue+echarts 数据可视化大屏展示的方法示例
2020/03/09 Javascript
openlayers 3实现车辆轨迹回放
2020/09/24 Javascript
[09:13]2014DOTA2国际邀请赛 中国区预选赛coser表演
2014/05/23 DOTA
Windows下用py2exe将Python程序打包成exe程序的教程
2015/04/08 Python
浅谈插入排序算法在Python程序中的实现及简单改进
2016/05/04 Python
在Python中定义和使用抽象类的方法
2016/06/30 Python
详解Django的CSRF认证实现
2018/10/09 Python
python如何查看微信消息撤回
2018/11/27 Python
Python获取统计自己的qq群成员信息的方法
2019/11/15 Python
Python使用扩展库pywin32实现批量文档打印实例
2020/04/09 Python
30行Python代码实现高分辨率图像导航的方法
2020/05/22 Python
协程Python 中实现多任务耗资源最小的方式
2020/10/19 Python
瑞典香水、须后水和美容产品购物网站:Parfym-Klick.se
2019/12/29 全球购物
Java程序开发中如何应用线程
2016/03/03 面试题
个人评价范文分享
2014/01/11 职场文书
房产转让协议书
2014/04/11 职场文书
诚信教育主题班会
2015/08/13 职场文书
学风建设主题班会
2015/08/17 职场文书
Jupyter Notebook内使用argparse报错的解决方案
2021/06/03 Python
MySQL中IF()、IFNULL()、NULLIF()、ISNULL()函数的使用详解
2021/06/26 MySQL
node.js如何自定义实现一个EventEmitter
2021/07/16 Javascript