将jQuery用于白名单标签是否明智? JavaScript中是否存在现有解决方案?

我的问题

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

目前我认为无法在服务器上执行此操作,因此我想它必须在JavaScript中完成。

目前的想法

我找到了jquery-clean插件 ,但据我所知,它正在使用正则表达式来完成工作, 我们知道这不安全 。

由于我没有找到任何其他基于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 aa 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 = $('
').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 = $(''); 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; }

我想知道一些要点(见代码中的评论);

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

如果您利用浏览器的HTML纠正function(例如,您将富文本复制到空divinnerHTML并获取生成的DOM树),HTML将保证有效(将纠正的方式与浏览器有关)。 虽然这可能是由富有的编辑器完成的。

jQuery自己的文本顶级DOM转换可能也是安全的,但肯定更慢,所以我会避免它。

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