必须杜绝拼接$_get到sql或html,改用类型约束、预处理语句、白名单校验和上下文敏感转义:数字强制int过滤,字符串走pdo预处理,枚举值严格白名单,html输出用htmlspecialchars,js字符串用json_encode。

直接拼接 $_GET 到 SQL 或 HTML 中是高危操作,不能靠“过滤”来补救,而必须彻底避免拼接本身。所谓“怎么过滤”,本质是误入歧途——真正要做的,是切断拼接路径,改用安全机制。
为什么不能对 $_GET 做“拼接前过滤”?
-
addslashes()、mysqli_real_escape_string()等字符串转义函数,只在特定字符集和上下文里有效,且完全不适用于数字、布尔、NULL 或 JSON 类型参数; -
htmlspecialchars()是输出层防护,用于 HTML 渲染,对 SQL 查询无效,反而可能破坏数据(比如把O'Reilly变成O'Reilly后入库); - 白名单正则、删
or、union等关键词的“黑盒清洗”,极易被绕过(如大小写混写、编码变形、注释干扰),属于伪安全。
数字类参数(如 id、page、limit)
- 不允许字符串参与运算,强制类型约束:
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT); if ($id === false || $id
字符串类参数(如 username、search、email)
-
绝不拼接进 SQL,一律走预处理语句:
$stmt = $pdo->prepare("SELECT * FROM user WHERE username = ?"); $stmt->execute([$_GET['username'] ?? '']); // 注意:此处仍需先校验非空、长度、格式 - 若需校验,用
filter_var():$email = filter_input(INPUT_GET, 'email', FILTER_VALIDATE_EMAIL); if (!$email) { /* 拒绝 */ }
枚举/状态类参数(如 status=active、type=article)
- 必须白名单校验,不接受任何未声明值:
$status = $_GET['status'] ?? ''; if (!in_array($status, ['draft', 'active', 'archived'], true)) { http_response_code(400); exit('Invalid status'); }
输出到 HTML 页面时(唯一该用 htmlspecialchars 的地方)
- 仅在 echo 或 print 插入 HTML 内容前转义:
<p>搜索结果:= htmlspecialchars($_GET['q'] ?? '', ENT_QUOTES, 'UTF-8') ?></p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/learn/6880" title="独孤系列php教程源码"><img src="https://img.php.cn/upload/webcode/000/000/164/60fe5a38ebc02853.jpg" alt="独孤系列php教程源码" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/learn/6880" title="独孤系列php教程源码" class="overflowclass">独孤系列php教程源码</a> <p class="overflowclass">独孤系列php教程源码</p> </div> <a rel="nofollow" href="/xiazai/learn/6880" title="独孤系列php教程源码" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>
- 输出到
<input value="...">属性中,同样要用ENT_QUOTES; - 输出到 JavaScript 字符串中,改用
json_encode():<script>var q = <?= json_encode($_GET['q'] ?? '', JSON_UNESCAPED_UNICODE) ?>;</script>
不复杂但容易忽略










