【问题标题】:Escape HTML using jQuery [duplicate]使用 jQuery 转义 HTML [重复]
【发布时间】:2011-08-26 14:47:29
【问题描述】:

我想出了一个使用 jQuery 转义 HTML 的技巧,我想知道是否有人发现它有问题。

$('<i></i>').text(TEXT_TO_ESCAPE).html();

&lt;i&gt; 标签只是一个虚拟标签,因为 jQuery 需要一个容器来设置其文本。

是否有更简单的方法来做到这一点?请注意,我需要将文本存储在变量中,而不是用于显示(否则我可以直接调用 elem.text(TEXT_TO_ESCAPE);)。

谢谢!

【问题讨论】:

  • “转义 HTML”到底是什么意思?是否要将 &lt;&gt;&amp; 等字符转换为对应的 HTML 实体?
  • 您的示例可以缩短为:$('&lt;i&gt;').text(TEXT_TO_ESCAPE).html();

标签: javascript jquery html escaping


【解决方案1】:

这是一种非常标准的做法,但我的版本使用了&lt;div&gt;

return $('<div/>').text(t).html();

尽管正如 Mike Samuel 所说,这在技术上并不是 100% 安全的,但在实践中可能相当安全。

当前的 Prototype.js 是这样做的:

function escapeHTML() {
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}

但它曾经使用“将文本放入 div 并提取 HTML”的技巧。

还有_.escape in Underscore,就是这样的:

// List of HTML entities for escaping.
var htmlEscapes = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#x27;',
  '/': '&#x2F;'
};

// Regex containing the keys listed immediately above.
var htmlEscaper = /[&<>"'\/]/g;

// Escape a string for HTML interpolation.
_.escape = function(string) {
  return ('' + string).replace(htmlEscaper, function(match) {
    return htmlEscapes[match];
  });
};

这与 Prototype 的方法几乎相同。我最近做的大部分 JavaScript 都有下划线,所以这些天我倾向于使用 _.escape

【讨论】:

  • 很多图书馆都这样做。请注意,此处的结果可以安全地嵌入到 PCDATA 上下文和 RCDATA 上下文中,但不是属性上下文,因为引号不会被转义。如果您可能容易受到 UTF-7 攻击等,您还应该转义“+”:en.wikipedia.org/wiki/UTF-7#Security
  • @Mike:我不认为.text(t).html() 或Prototype 的replace 方法真的那么好,两种方法都有问题。标准 JavaScript 库中缺少 encodeHTML() 函数是一个巨大的漏洞,也是一个相当令人惊讶的疏忽。
  • @muis:我不这么认为:核心 JavaScript 语言并不是专门针对网络浏览器的。
  • @Marcel:但我们确实有encodeURIComponent,JavaScript 的根源在于网络浏览器。而且,每个人最终都编写自己的事实表明标准库存在差距。
  • @muis 感谢您提供指向原型的指针。事实证明,我提出的方法在某些浏览器中无法正常工作(阅读:IE)
【解决方案2】:

无法保证html() 会被完全转义,因此连接后的结果可能不安全。

html() 基于innerHTML,浏览器可以在不违背很多期望的情况下实现innerHTML,从而$("&lt;i&gt;&lt;/i&gt;").text("1 &lt;").html()"1 &lt;",而$("&lt;i&gt;&lt;/i&gt;").text("b&gt;").html()"b&gt;"

如果你连接这两个单独安全的结果,你会得到"1 &lt;b&gt;",这显然不是连接两个纯文本片段的 HTML 版本。

因此,从第一原理推断,这种方法并不安全,并且没有广泛遵循的 innerHTML 规范(尽管 HTML5 确实解决了它)。

检查它是否符合您的要求的最佳方法是像这样测试极端情况。

【讨论】:

  • 实际上,我希望$("&lt;i&gt;&lt;/i&gt;").text("1 &lt;").html() 成为"1 &amp;lt;"$("&lt;i&gt;&lt;/i&gt;").text("b&gt;").html() 成为"b&amp;gt;"。 (有效)
  • @Michael,如果您已经在主流浏览器上测试过它,并且它可以工作,那就太好了。截至 2009 年 6 月 15 日,当前版本的 Safari 实际上未转义 >所以 &lt;input name="Hello&amp;gt;World"&gt; 通过 innerHTML 返回为 &lt;input name="Hello&gt;World"&gt;。不过,这可能已在现代浏览器中得到修复。我的观点是,测试是获得信心的方式。
【解决方案3】:

应该可以。这基本上就是 Prototype.js 库的工作方式,或者至少是它过去的工作方式。我通常通过三个调用“.replace()”来做到这一点,但这主要只是一种习惯。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    • 2013-05-27
    • 2012-07-05
    • 2012-06-06
    • 2021-12-14
    • 2016-05-02
    相关资源
    最近更新 更多