我想允许很多用户为用户个人资料提交html,我目前试图过滤掉我不想要的内容,但我现在想要更改并使用白名单方法。
这是我目前的非白名单方法
function FilterHTML($string) {
if (get_magic_quotes_gpc()) {
$string = stripslashes($string);
}
$string = html_entity_decode($string, ENT_QUOTES, "ISO-8859-1");
// convert decimal
$string = preg_replace('/&#(\d+)/me', "chr(\\1)", $string); // decimal notation
// convert hex
$string = preg_replace('/&#x([a-f0-9]+)/mei', "chr(0x\\1)", $string); // hex notation
//$string = html_entity_decode($string, ENT_COMPAT, "UTF-8");
$string = preg_replace('#(&\#*\w+)[\x00-\x20]+;#U', "$1;", $string);
$string = preg_replace('#(<[^>]+[\s\r\n\"\'])(on|xmlns)[^>]*>#iU', "$1>", $string);
//$string = preg_replace('#(&\#x*)([0-9A-F]+);*#iu', "$1$2;", $string); //bad line
$string = preg_replace('#/*\*()[^>]*\*/#i', "", $string); // REMOVE /**/
$string = preg_replace('#([a-z]*)[\x00-\x20]*([\`\'\"]*)[\\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iU', '...', $string); //JAVASCRIPT
$string = preg_replace('#([a-z]*)([\'\"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iU', '...', $string); //VBSCRIPT
$string = preg_replace('#([a-z]*)[\x00-\x20]*([\\\]*)[\\x00-\x20]*@([\\\]*)[\x00-\x20]*i([\\\]*)[\x00-\x20]*m([\\\]*)[\x00-\x20]*p([\\\]*)[\x00-\x20]*o([\\\]*)[\x00-\x20]*r([\\\]*)[\x00-\x20]*t#iU', '...', $string); //@IMPORT
$string = preg_replace('#([a-z]*)[\x00-\x20]*e[\x00-\x20]*x[\x00-\x20]*p[\x00-\x20]*r[\x00-\x20]*e[\x00-\x20]*s[\x00-\x20]*s[\x00-\x20]*i[\x00-\x20]*o[\x00-\x20]*n#iU', '...', $string); //EXPRESSION
$string = preg_replace('#</*\w+:\w[^>]*>#i', "", $string);
$string = preg_replace('#</?t(able|r|d)(\s[^>]*)?>#i', '', $string); // strip out tables
$string = preg_replace('/(potspace|pot space|rateuser|marquee)/i', '...', $string); // filter some words
//$string = str_replace('left:0px; top: 0px;','',$string);
do {
$oldstring = $string;
//bgsound|
$string = preg_replace('#</*(applet|meta|xml|blink|link|script|iframe|frame|frameset|ilayer|layer|title|base|body|xml|AllowScriptAccess|big)[^>]*>#i', "...", $string);
} while ($oldstring != $string);
return addslashes($string);
}
上面的工作非常好,经过2年的使用后我从来没有遇到过任何问题,但是对于白名单方法,有什么类似于stackoverflows的C#方法,但是在PHP中? http://refactormycode.com/codes/333-sanitize-html
答案 0 :(得分:13)
HTML Purifier是一个 符合标准的HTML过滤器 用PHP编写的库。 HTML净化器 不仅会删除所有恶意内容 用a代码(更好地称为XSS) 彻底审核,安全 容许白名单,它也会 确保你的文件是 符合标准,只有一些东西 可以全面实现 了解W3C的规范。
答案 1 :(得分:8)
使用DOMDocument正确分析它可能更安全,使用removeChild()删除不允许的标记然后获取结果。 使用正则表达式过滤东西并不总是安全的,特别是如果事情开始变得如此复杂。黑客可以找到一种方法来欺骗你的过滤器,论坛和社交网络都很清楚。
例如,浏览器在&lt;之后忽略空格。您的正则表达式过滤器&lt;脚本,但如果我使用&lt;脚本...大失败!
答案 2 :(得分:3)
HTML Purifier是最好的HTML解析器/清理器。
答案 3 :(得分:1)
对于那些建议只使用strip_tags的人......请注意:strip_tags不会删除标记属性,破坏的标记也会搞砸。
从手册页:
警告因为strip_tags()实际上不会验证HTML,部分或损坏的标记会导致删除比预期更多的文本/数据。
警告此功能不会修改 您标记的任何属性 允许使用allowable_tags,包括 样式和onmouseover属性 一个恶作剧的用户可能会滥用 发布将显示的文本 其他用户。
你不能只依赖这一个解决方案。
答案 4 :(得分:0)
您可以使用strip_tags()函数
由于该功能定义为
string strip_tags ( string $str [, string $allowable_tags ] )
你可以这样做:
$html = $_POST['content'];
$html = strip_tags($html, '<b><a><i><u><span>');
但请注意,使用strip_tags,您将无法过滤掉属性。 e.g。
<a href="javascript:alert('haha caught cha!');">link</a>
答案 5 :(得分:0)
在下面尝试此功能“getCleanHTML”,从元素中提取文本内容,但白名单中带有标记名称的元素除外。这段代码干净,易于理解和调试。
<?php
$TagWhiteList = array(
'b', 'i', 'u', 'strong', 'em', 'a', 'img'
);
function getHTMLCode($Node) {
$Document = new DOMDocument();
$Document->appendChild($Document->importNode($Node, true));
return $Document->saveHTML();
}
function getCleanHTML($Node, $Text = "") {
global $TagWhiteList;
$TextName = $Node->tagName;
if ($TextName == null)
return $Text.$Node->textContent;
if (in_array($TextName, $TagWhiteList))
return $Text.getHTMLCode($Node);
$Node = $Node->firstChild;
if ($Node != null)
$Text = getCleanHTML($Node, $Text);
while($Node->nextSibling != null) {
$Text = getCleanHTML($Node->nextSibling, $Text);
$Node = $Node->nextSibling;
}
return $Text;
}
$Doc = new DOMDocument();
$Doc->loadHTMLFile("Test.html");
echo getCleanHTML($Doc->documentElement)."\n";
?>
希望这有帮助。
答案 6 :(得分:-1)
这实际上是一个非常简单的目标 - 您只需要检查白名单标签列表中的某些标签,并将其从源中删除。一个正则表达式可以很容易地完成它。
function sanitize($html) {
$whitelist = array(
'b', 'i', 'u', 'strong', 'em', 'a'
);
return preg_replace("/<(^".implode("|", $whitelist).")(.*)>(.*)<\/(^".implode("|", $whitelist).")>/", "", $html);
}
我还没有对此进行过测试,并且在某处可能存在错误,但您可以了解其工作原理。您可能还希望使用诸如Textile或Markdown之类的格式化语言。
杰米