【问题标题】:Is it wise to use jQuery for whitelisting tags? Are there existing solutions in JavaScript?使用 jQuery 将标签列入白名单是否明智? JavaScript 中是否有现有的解决方案?
【发布时间】:2011-07-17 07:20:34
【问题描述】:

我的问题

我想清理粘贴在富文本编辑器(目前为 FCK 1.6)中的 HTML。清理应该基于标签的白名单(可能还有另一个带有属性的)。这主要不是为了防止 XSS,而是为了移除丑陋的 HTML。

目前我看不到在服务器上这样做,所以我想它必须在 JavaScript 中完成。

当前想法

我找到了jquery-clean plugin,但据我所知,它正在使用正则表达式来完成这项工作,而we know that is not safe

由于我还没有找到任何其他基于 JS 的解决方案,因此我开始使用 jQuery 自己实现一个。它可以通过创建粘贴的 html ($(pastedHtml)) 的 jQuery 版本来工作,然后遍历结果树,通过查看属性 tagName 删除每个不匹配白名单的元素。

我的问题

  • 这样更好吗?
  • 我可以相信 jQuery 来代表粘贴的吗 内容很好(可能有无与伦比的 结束标签和你有什么)?
  • 是否已经有更好的解决方案 没找到?

更新

这是我目前基于 jQuery 的解决方案(详细且未经广泛测试):

function clean(element, whitelist, replacerTagName) {
    // Use div if no replace tag was specified
    replacerTagName = replacerTagName || "div";

    // Accept anything that jQuery accepts
    var jq = $(element);    

    // Create a a copy of the current element, but without its children
    var clone = jq.clone();
    clone.children().remove();

    // Wrap the copy in a dummy parent to be able to search with jQuery selectors
    // 1)
    var wrapper = $('<div/>').append(clone);

    // Check if the element is not on the whitelist by searching with the 'not' selector
    var invalidElement = wrapper.find(':not(' + whitelist + ')');

    // If the element wasn't on the whitelist, replace it.
    if (invalidElement.length > 0) {
       var el = $('<' + replacerTagName + '/>'); 
       el.text(invalidElement.text()); 
       invalidElement.replaceWith(el);   
    }

    // Extract the (maybe replaced) element
    var cleanElement = $(wrapper.children().first());

    // Recursively clean the children of the original element and
    // append them to the cleaned element
    var children = jq.children();
    if (children.length > 0) {
        children.each(function(_index, thechild) {
                          var cleaned = clean(thechild, whitelist, replacerTagName);
                          cleanElement.append(cleaned);
                      });
      } 
    return cleanElement;
}

我想知道一些点(见代码中的 cmets);

  1. 我真的需要将我的元素包装在一个虚拟父元素中以便能够与 jQuery 的 ":not" 匹配吗?
  2. 这是推荐的创建新节点的方法吗?

【问题讨论】:

  • 我无法在评论中建议如何在服务器端完成此操作,但最终用户可以访问 JS,我们不信任最终用户。 可以在客户端完成,但也需要在服务器端进行检查。
  • @David Thomas:这就是为什么我写“主要不是为了防止 XSS”,但我也看到了它如何应用于我的用例。但是,我的环境是现有的 CMS,在服务器端进行操作会困难得多。还值得一提的是,编辑器的用户是登录的员工,他们可以访问不断变化的页面内容甚至网站结构。
  • 我的意思是,如果他们愿意,他们可以制造破坏。我只是想让犯错更难,更容易做正确的事。
  • ahhh... 好吧,在这种情况下,客户端可能没问题:)

标签: javascript jquery fckeditor whitelist


【解决方案1】:

如果您利用浏览器的 HTML 更正功能(例如,您将富文本复制到空 divinnerHTML 并获取生成的 DOM 树),则 HTML 将被保证是有效的(它的方式将更正有点依赖于浏览器)。虽然这可能是由富编辑器完成的。

jQuery 自己的 text-top DOM 转换可能也是安全的,但肯定比较慢,所以我会避免它。

使用基于 jQuery 选择器引擎的白名单可能有点棘手,因为在保留其子元素的同时删除元素可能会使文档无效,因此浏览器会通过更改 DOM 树来纠正它,这可能会混淆尝试迭代的脚本通过无效元素。 (例如,您允许ulli 但不允许ol;脚本删除列表根元素,裸li 元素无效,因此浏览器再次将它们包装在ul 中,ul 将被遗漏通过清理脚本。)如果你把不需要的元素和他们所有的孩子一起扔掉,我看不出有什么问题。

【讨论】:

  • 谢谢!你提出了一个我什至没有想到的问题。我已经用我当前解决方案的源代码更新了我的问题,我没有考虑到你在说什么。当我运行我的函数时,它确实返回了无效的 HTML(我已经通过允许 li 但将 ul 替换为例如 div 来尝试您的示例)并且我可以将它添加到 DOM 中。这是 Ubuntu 中的 Chromium。我也得看看它在其他浏览器中是如何工作的。
  • 关于 jQuery 性能...如果 jQuery 不是特别慢(我不这么认为),我怀疑用户在将 HTML 粘贴到编辑器文本区域时会注意到。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多