XSS攻击本质是用户数据未经消毒直接嵌入HTML,关键在输出时转义而非输入过滤;HTML文本用htmlspecialchars($data, ENT_QUOTES, 'UTF-8'),属性值须加引号,JS/JSON中用json_encode()。

XSS攻击的本质,是把用户可控的数据未经处理就直接嵌入到HTML页面中,浏览器把它当成了可执行代码。关键不在“输入有没有坏”,而在于“输出时有没有消毒”。所以过滤的重点不是拦住什么,而是让数据在特定位置安全地显示出来。
输出到HTML文本内容时用 htmlspecialchars()
这是最常见场景,比如显示用户昵称、评论、搜索关键词等。必须对每个要 echo 或 print 的变量做转义:
- 用 htmlspecialchars($data, ENT_QUOTES, 'UTF-8') —— ENT_QUOTES 能同时转义单引号和双引号,防止属性注入
- 别只依赖默认参数,
htmlspecialchars($data)不转单引号,存在绕过风险 - 不要用
htmlentities()处理中文内容,它可能把汉字错转成乱码实体
输出到HTML属性值里要更谨慎
比如 <input value="<script>..."> 这类写法,光用 htmlspecialchars 不够稳:
- 确保属性值始终用英文双引号或单引号包裹(如
value="<?php echo htmlspecialchars($val, ENT_QUOTES); ?>") - 避免把用户数据拼进未加引号的属性(如
class=<?php echo $user_class; ?>),这种写法极易被突破 - 能不用内联属性就不用,优先走 data-* 属性 + JS 控制逻辑
输出到 JavaScript 或 JSON 中要用 json_encode()
如果要把 PHP 变量塞进 <script> 标签或 AJAX 返回的 JSON 里,htmlspecialchars 不适用:
立即学习“PHP免费学习笔记(深入)”;
- 用 json_encode($data, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP),再包一层引号
- 示例:
<script>var name = <?php echo json_encode($name, JSON_UNESCAPED_UNICODE); ?>;</script> - 绝对不要用
" + <?php echo $name; ?> + "这种字符串拼接方式
富文本内容不能靠简单转义,得用专用清理器
如果业务允许用户发带格式的文章、评论(含 <b>、<img> 等),htmlspecialchars 会把所有标签都干掉,体验差:
- 引入 HTMLPurifier 库,配置白名单(只留 <p>、<strong>、<a> 等安全标签)
- 禁用危险属性:onerror、onclick、javascript: 协议、style 中的 expression 等
- 存储前清理一次,输出时仍建议再过一遍
htmlspecialchars(双重保险)



















