本文目录导读:

在PHP项目中处理富文本安全过滤,核心原则是白名单机制(只允许特定标签/属性)而非黑名单,以下是主流方案及代码示例:
专业库方案(推荐)
HTMLPurifier(行业标准)
require_once '/path/to/HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.Allowed', 'p,b,i,u,a[href|target],img[src|alt]'); // 白名单
$config->set('URI.AllowedSchemes', ['http','https','mailto']);
$config->set('AutoFormat.RemoveEmpty', true); // 移除空标签
$purifier = new HTMLPurifier($config);
$clean_html = $purifier->purify($dirty_html);
特点
- 严格遵循W3C标准
- 防御XSS、CSS注入、URL欺骗等
- 可以自定义标签/属性白名单
- 约2MB大小,适合生产环境
轻量级方案(适用于简单场景)
使用strip_tags + 自定义处理
function safeRichText($html) {
// 1. 基础过滤(只保留指定标签)
$allowed = '<p><br><b><i><u><a><img><ul><ol><li><blockquote>';
$html = strip_tags($html, $allowed);
// 2. 移除事件处理器
$html = preg_replace('/\son\w+="[^"]*"/i', '', $html);
// 3. 清理javascript链接
$html = preg_replace('/href="javascript:[^"]*"/i', 'href="#"', $html);
// 4. XSS防御
$html = htmlspecialchars_decode($html); // strip_tags已编码,需要解码后重新处理
// 实际建议使用更全面的过滤
return $html;
}
注意:此方法不够安全,不建议单独用于用户输入。
HTML输入解析过滤法(推荐中级项目)
使用DOMDocument解析后遍历过滤:
function filterRichText($html) {
$allowedTags = ['p','br','strong','em','a','img','ul','ol','li','blockquote'];
$allowedAttrs = ['href','src','alt','title'];
$allowedProtocols = ['http','https','mailto'];
libxml_use_internal_errors(true);
$dom = new DOMDocument();
@$dom->loadHTML('<?xml encoding="UTF-8">' . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
// 递归移除违规元素
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//*');
foreach ($nodes as $node) {
// 检查标签是否允许
if (!in_array($node->nodeName, $allowedTags)) {
$node->parentNode->removeChild($node);
continue;
}
// 过滤属性
$attrsToRemove = [];
foreach ($node->attributes as $attr) {
if (!in_array($attr->nodeName, $allowedAttrs)) {
$attrsToRemove[] = $attr;
}
}
foreach ($attrsToRemove as $attr) {
$node->removeAttribute($attr->nodeName);
}
// 特殊处理href协议
if ($node->hasAttribute('href')) {
$href = $node->getAttribute('href');
$protocol = parse_url($href, PHP_URL_SCHEME);
if ($protocol && !in_array($protocol, $allowedProtocols)) {
$node->removeAttribute('href');
}
}
}
$result = '';
foreach ($dom->childNodes as $child) {
$result .= $dom->saveHTML($child);
}
return $result;
}
安全配置示例(HTMLPurifier详细配置)
$config = HTMLPurifier_Config::createDefault();
// 白名单设置
$config->set('HTML.Allowed',
'h1,h2,h3,h4,p,br,strong,em,span[style],' .
'ul,ol,li,a[href|title|target],' .
'img[src|alt|width|height],' .
'blockquote,pre,code,hr'
);
// 允许的CSS属性
$config->set('CSS.AllowedProperties', 'color,background-color,font-size,text-align');
// 禁止iframe/object/embed等风险标签
$config->set('HTML.ForbiddenElements', ['iframe','object','embed','applet','script','style']);
// 自动移除无效嵌套
$config->set('AutoFormat.AutoParagraph', true);
$config->set('AutoFormat.RemoveEmpty', true);
// 链接配置
$config->set('URI.AllowedSchemes', ['http','https','mailto','ftp']);
$config->set('URI.DisableExternalResources', false);
$config->set('URI.Host', $_SERVER['HTTP_HOST']); // 限制本域资源
// 编码
$config->set('Core.Encoding', 'UTF-8');
输出时的额外保护
// 存储时保持原始格式 $safe_html = $purifier->purify($input_html); // 输出时(特别是模板渲染时)进行HTML实体编码 echo htmlspecialchars($safe_html, ENT_QUOTES | ENT_HTML5, 'UTF-8');
安全建议
- 绝对不要使用
strip_tags()作为唯一过滤 - 避免黑名单(如过滤
<script>),总有绕过的可能 - 严格控制
style属性的使用(可能有CSS注入) - 不要信任
data:协议(可嵌入恶意内容) - 配置CDN 增加CSP头进行二次防护:
Content-Security-Policy: default-src 'self'; script-src 'none'; style-src 'unsafe-inline'
性能考虑
- HTMLPurifier 处理500字符约需0.1-0.3ms
- 建议对用户输入做缓存(如摘要缓存)>10KB)建议异步处理或使用消息队列
选择方案时请根据项目需求权衡:生产环境强安全建议用HTMLPurifier,简单场景可用DOMDocument+白名单,但切勿自行实现完整HTML解析器。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播