您当前的位置:首页 > 计算机 > 编程开发 > PHP

htmlspecialchars(strip_tags($text, ‘<p><a>‘), ENT_QUOTES, ‘UTF-8‘);,知识体系一共包含哪些部分?底层原理是什么?

时间:10-29来源:作者:点击数:
CDSY,CDSY.XYZ
htmlspecialchars(strip_tags($text, '<p><a>'), ENT_QUOTES, 'UTF-8');

是 PHP 中一种常见的“双重过滤”模式,用于在输出 HTML 时防止 XSS 攻击。它结合了两个函数,层层设防,是许多开发者在处理用户输入时的“安全习惯”。

但要真正理解它,必须掌握其背后的知识体系与底层原理


一、知识体系总览

模块 核心内容
1. strip_tags() 函数 去除 HTML 标签,保留白名单
2. htmlspecialchars() 函数 转义特殊字符,防止 XSS
3. 双重过滤逻辑 先去标签,再转义剩余内容
4. XSS 防御机制 防止 <script>onerrorjavascript:
5. 字符编码与安全 UTF-8 的重要性
6. 白名单 <p><a> 的作用 允许部分富文本
7. 安全边界与局限 仍无法完全防御富文本攻击
8. 与 HTMLPurifier 对比 为什么它不够用
9. Laravel Blade 的等价写法 {!! clean($html) !!} vs {{ $text }}
10. 性能与使用场景 快速但有限
11. 常见误用与陷阱 顺序错误、编码错误
12. 底层原理:正则 vs 字符替换  
13. 最佳实践 何时用,何时不用
14. 源码级解析 PHP 内部实现

二、逐层解析这行代码

✅ 1. strip_tags($text, '<p><a>')
  • 作用:去除所有 HTML 标签,只保留 <p> 和 <a>
  • 原理:正则匹配 <...>,不在白名单中的删除
  • 输入
    <p>欢迎访问 <a href="javascript:alert(1)">网站</a></p><script>alert(1)</script>
    
  • 输出
    <p>欢迎访问 <a href="javascript:alert(1)">网站</a></p>
    

⚠️ 注意:<script> 被删了,但 <a href="javascript:..."> 依然存在!


✅ 2. htmlspecialchars(..., ENT_QUOTES, 'UTF-8')
  • 作用:将特殊字符转为 HTML 实体
  • 转义规则
    • < → &lt;
    • > → &gt;
    • & → &amp;
    • " → &quot;(因 ENT_QUOTES
    • ' → &#039;(因 ENT_QUOTES
  • 输入
    <p>欢迎访问 <a href="javascript:alert(1)">网站</a></p>
    
  • 输出
    &lt;p&gt;欢迎访问 &lt;a href=&quot;javascript:alert(1)&quot;&gt;网站&lt;/a&gt;&lt;/p&gt;
    

✅ 最终在页面上显示为纯文本,不会执行 JS


三、底层原理详解

✅ 1. strip_tags() 的实现(简化版)
// PHP 源码逻辑(伪代码)
while (preg_match('/<([^>]+)>/', $str, $matches)) {
    $tag = strtolower($matches[1]);
    if (!in_array($tag, $allowable_tags)) {
        $str = str_replace($matches[0], '', $str);
    }
}

✅ 只做字符串替换,不解析属性


✅ 2. htmlspecialchars() 的实现
// C 层实现(核心)
switch (char) {
    case '<':  return "&lt;";
    case '>':  return "&gt;";
    case '&':  return "&amp;";
    case '"':  return "&quot;";
    case '\'': return "&#039;";
}

✅ 是字符级替换,非常快


✅ 3. 为什么顺序不能反?
// ❌ 错误顺序
strip_tags(htmlspecialchars($text), '<p><a>');
  • htmlspecialchars() 先把 < 变成 &lt;
  • strip_tags() 找不到 <p>,无法保留标签
  • 结果:所有标签都被当作文本保留

✅ 必须先 strip_tags,再 htmlspecialchars


四、安全机制分析

✅ 防御了哪些攻击?
攻击类型 是否防御 说明
<script>alert(1)</script> ✅ 是 被 strip_tags 删除
<img src=x onerror=alert(1)> ✅ 是 标签被删
<a href="javascript:alert(1)"> ✅ 是 被 htmlspecialchars 转义,变成文本
直接输出 <p>文本</p> ✅ 是 保留结构,但无攻击性

❌ 仍存在的风险(局限性)
风险 说明
富文本场景不足 不能安全支持 imgstyleiframe
无法修复 HTML 结构 如 <p>hello 不会自动闭合
性能问题 对长文本多次处理
不是真正的 HTML 过滤器 比不上 HTMLPurifier

五、与 Laravel Blade 的对比

写法 等价于
{{ $text }} echo htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
{!! $html !!} echo $html;(危险!)
{!! clean($html) !!} echo HTMLPurifier::clean($html);(推荐)

✅ 推荐:在 Laravel 中使用 mewebstudio/laravel-purifier


六、最佳实践

✅ 推荐使用场景
  1. 纯文本摘要:文章列表页的描述
  2. 简单富文本:只允许 <p><a> 的评论
  3. 快速过滤:性能敏感场景
❌ 避免使用场景
  • 用户发布的文章内容
  • 富文本编辑器输出
  • 需要支持 imgvideotable 的场景

七、性能与编码

选项 说明
ENT_QUOTES 转义单引号和双引号,更安全
'UTF-8' 指定编码,防止多字节字符攻击
不指定编码 可能导致乱码或绕过

✅ 必须指定 'UTF-8'


八、总结

这行代码的本质

通过“先去标签,再转义”两层防御,将用户输入的安全性提升到“基本可用”水平

核心原理
  • strip_tags():基于正则的标签过滤(白名单)
  • htmlspecialchars():字符级转义,防 XSS
  • 顺序不可逆:必须先去标签,再转义
  • 编码必须指定UTF-8 防多字节攻击
  • 仍是简单方案:不适合富文本
成功关键

✅ 理解它是“轻量级防御”

✅ 用于简单场景(如摘要)

✅ 富文本用 HTMLPurifier

✅ Laravel 中用 {!! clean($html) !!}


一句话总结:

htmlspecialchars(strip_tags(...)) 是一把“双保险锁”——它不能防住所有攻击,但能挡住最常见的 XSS 子弹。

掌握它,你就能在简单场景下写出安全的 PHP 代码。

CDSY,CDSY.XYZ
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐