我使用 jQuery 来缩短我的答案并包含更少的样板代码,但这并不相关。
我正在使用它是.innerHTML
因为它不会在 html 中执行可能的脚本或 css。
在这里演示http://jsfiddle.net/QCaGq/
function filterData(data, options ){
var root;
try {
root = document.implementation.createHTMLDocument().body;
}
catch(e) {
root = document.createElement("body");
}
root.innerHTML = data;
$(root).find("*").filter(function(){
return options.allowTags.indexOf(this.tagName.toLowerCase()) === -1;
}).each( function() {
$(this).children().detach().insertBefore( this );
$(this).remove();
});
function removeStyle( node, attr ) {
var style = node.style,
prop,
name,
len = style.length,
i, val = "";
for( i = 0; i < len; ++i ) {
name = style[i];
prop = style[name];
if( options.allowSafeStyle.indexOf( name ) > -1 ) {
val += (name + ":" + prop + ";");
}
}
if( val ) {
attr.nodeValue = val;
}
else {
node.removeAttribute("style");
}
}
function removeAttrs( node ) {
$.each( node.attributes, function( index, attr ) {
if( !attr ) {
return;
}
if( attr.name.toLowerCase() === "style" ) {
return removeStyle( node, attr );
}
if( options.allowAttrs.indexOf(attr.name.toLowerCase()) === -1 ) {
node.removeAttribute(attr.name);
}
});
}
function walk( root ) {
removeAttrs(root);
$( root.childNodes ).each( function() {
if( this.nodeType === 8 ) { //Remove html comments
$(this).remove();
}
else if( this.nodeType === 1 ) {
walk(this);
}
});
}
walk(root);
return root.innerHTML;
}
var opts = {
allowTags: ["b", "i"],
allowAttrs: ["data-myapp"],
allowSafeStyle: ["color"]
}
filterData( '<b onclick="alert(\'XSS\');" data-myapp="asdf" style="color:red">Hello</b>\n<h1><i style="color:expression(alert(\'XSS\'));"> World</i></h1>', opts );
结果是:
<b data-myapp="asdf" style="color:red;">Hello</b>
<i> World</i>
这应该让你开始。