htmlspecialchars(strip_tags($text, '<p><a>'), ENT_QUOTES, 'UTF-8');
是 PHP 中一种常见的“双重过滤”模式,用于在输出 HTML 时防止 XSS 攻击。它结合了两个函数,层层设防,是许多开发者在处理用户输入时的“安全习惯”。
但要真正理解它,必须掌握其背后的知识体系与底层原理。
| 模块 | 核心内容 |
|---|---|
| 1. strip_tags() 函数 | 去除 HTML 标签,保留白名单 |
| 2. htmlspecialchars() 函数 | 转义特殊字符,防止 XSS |
| 3. 双重过滤逻辑 | 先去标签,再转义剩余内容 |
| 4. XSS 防御机制 | 防止 <script>、onerror、javascript: |
| 5. 字符编码与安全 | UTF-8 的重要性 |
| 6. 白名单 <p><a> 的作用 | 允许部分富文本 |
| 7. 安全边界与局限 | 仍无法完全防御富文本攻击 |
| 8. 与 HTMLPurifier 对比 | 为什么它不够用 |
| 9. Laravel Blade 的等价写法 | {!! clean($html) !!} vs {{ $text }} |
| 10. 性能与使用场景 | 快速但有限 |
| 11. 常见误用与陷阱 | 顺序错误、编码错误 |
| 12. 底层原理:正则 vs 字符替换 | |
| 13. 最佳实践 | 何时用,何时不用 |
| 14. 源码级解析 | PHP 内部实现 |
<p>欢迎访问 <a href="javascript:alert(1)">网站</a></p><script>alert(1)</script>
<p>欢迎访问 <a href="javascript:alert(1)">网站</a></p>
⚠️ 注意:<script> 被删了,但 <a href="javascript:..."> 依然存在!
<p>欢迎访问 <a href="javascript:alert(1)">网站</a></p>
<p>欢迎访问 <a href="javascript:alert(1)">网站</a></p>
✅ 最终在页面上显示为纯文本,不会执行 JS
// PHP 源码逻辑(伪代码)
while (preg_match('/<([^>]+)>/', $str, $matches)) {
$tag = strtolower($matches[1]);
if (!in_array($tag, $allowable_tags)) {
$str = str_replace($matches[0], '', $str);
}
}
✅ 只做字符串替换,不解析属性
// C 层实现(核心)
switch (char) {
case '<': return "<";
case '>': return ">";
case '&': return "&";
case '"': return """;
case '\'': return "'";
}
✅ 是字符级替换,非常快
// ❌ 错误顺序
strip_tags(htmlspecialchars($text), '<p><a>');
✅ 必须先 strip_tags,再 htmlspecialchars
| 攻击类型 | 是否防御 | 说明 |
|---|---|---|
| <script>alert(1)</script> | ✅ 是 | 被 strip_tags 删除 |
| <img src=x onerror=alert(1)> | ✅ 是 | 标签被删 |
| <a href="javascript:alert(1)"> | ✅ 是 | 被 htmlspecialchars 转义,变成文本 |
| 直接输出 <p>文本</p> | ✅ 是 | 保留结构,但无攻击性 |
| 风险 | 说明 |
|---|---|
| 富文本场景不足 | 不能安全支持 img, style, iframe |
| 无法修复 HTML 结构 | 如 <p>hello 不会自动闭合 |
| 性能问题 | 对长文本多次处理 |
| 不是真正的 HTML 过滤器 | 比不上 HTMLPurifier |
| 写法 | 等价于 |
|---|---|
| {{ $text }} | echo htmlspecialchars($text, ENT_QUOTES, 'UTF-8'); |
| {!! $html !!} | echo $html;(危险!) |
| {!! clean($html) !!} | echo HTMLPurifier::clean($html);(推荐) |
✅ 推荐:在 Laravel 中使用 mewebstudio/laravel-purifier
| 选项 | 说明 |
|---|---|
| ENT_QUOTES | 转义单引号和双引号,更安全 |
| 'UTF-8' | 指定编码,防止多字节字符攻击 |
| 不指定编码 | 可能导致乱码或绕过 |
✅ 必须指定 'UTF-8'
通过“先去标签,再转义”两层防御,将用户输入的安全性提升到“基本可用”水平
✅ 理解它是“轻量级防御”
✅ 用于简单场景(如摘要)
✅ 富文本用 HTMLPurifier
✅ Laravel 中用 {!! clean($html) !!}
htmlspecialchars(strip_tags(...)) 是一把“双保险锁”——它不能防住所有攻击,但能挡住最常见的 XSS 子弹。
掌握它,你就能在简单场景下写出安全的 PHP 代码。

