必须验证json输入合法性并限制长度,解析后需类型检查、白名单过滤及上下文安全输出,不可将json视为已消毒数据源。

json_decode() 之前必须验证输入是否为合法 JSON
PHP 不会自动拒绝恶意构造的 JSON 输入,json_decode() 遇到格式错误时只返回 null,但若输入是看似合法、实则嵌套极深或含超长字符串的 JSON,可能触发解析器资源耗尽或静默截断。常见错误现象是:前端传了 {"user_id":"1' OR '1'='1"} 这类字符串,后端没校验就直接 decode,后续拼 SQL 或写日志时出问题——这不是 JSON 注入,而是下游使用不当引发的漏洞。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 用
json_validate()(PHP 8.3+)或json_last_error() === JSON_ERROR_NONE(兼容旧版)做前置校验 - 限制输入长度,比如
if (strlen($input) > 1024 * 100) { throw new InvalidArgumentException('JSON too large'); } - 避免直接把
$_POST['data']或file_get_contents('php://input')丢给json_decode()
不要用 json_decode($input, true) 处理不可信数据再拼接 SQL
开启第二个参数 true 会让 json_decode() 返回关联数组,看着方便,但容易让人忽略键名和值都来自外部——如果后续代码用 $data['username'] 拼 SQL,就等于把攻击面完全暴露给原始 JSON 字段名和内容。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 始终用
json_decode($input, false)(默认),保持对象结构,强制你显式访问$obj->username,至少多一层语义隔离 - 哪怕要用数组,也立刻用白名单过滤字段:
$allowed = ['email', 'phone']; $safe = array_intersect_key($arr, array_flip($allowed)); - 任何需要进 SQL 的值,必须过
mysqli_real_escape_string()或用 PDO 预处理——JSON 解析本身不解决注入,只是数据搬运环节
json_encode() 输出前注意上下文与字符编码
很多人以为只要输入安全,输出就一定安全,但 json_encode() 在 HTML 或 JavaScript 片段中直接输出时,可能被绕过:比如在 <script>var data = <?= json_encode($user) ?>;</script> 中,若 $user 含 字符串,浏览器会提前闭合 script 标签,执行后续 JS。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- HTML 内联 JS 中输出 JSON,必须加
JSON_HEX_TAG等标志:json_encode($data, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) - 确保输入字符串是 UTF-8 编码,否则
json_encode()可能返回false;可用mb_convert_encoding($str, 'UTF-8', 'auto')预处理 - 不要把
json_encode()结果直接 echo 到href、onclick等属性里,这类上下文需额外 HTML 实体转义
用 json_decode() + 类型约束替代宽松解析
默认的 json_decode() 对数字、布尔、null 全盘接受,但业务逻辑往往只接受整数 ID、邮箱格式字符串等。放任类型混杂,会导致后续判断分支出错,比如 if ($data->id == '1') {...} 在 "1" 和 1 上行为不一致。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 解析后立刻做类型断言:
if (!is_int($data->id) || $data->id - 用
filter_var()验证关键字段:filter_var($data->email, FILTER_VALIDATE_EMAIL) - 复杂结构考虑用
spatie/data-transfer-object或原生#[\ReturnTypeWillChange](PHP 8.2+)配合属性类型声明,让错误提前暴露
真正危险的从来不是 JSON 本身,而是把它当成“已消毒”的数据源。解析之后的每个字段,都要当作第一次接触的外部输入来对待——该转义的转义,该过滤的过滤,该类型检查的检查。漏掉任意一环,前面所有 JSON 处理都白做。











