自定义查询类防SQL注入必须强制使用预处理绑定,禁用模拟预处理,占位符仅用于数据值。动态表名需白名单映射,IN语句手动展开占位符。输入验证不能替代预处理,杜绝任何字符串拼接。
在自定义查询类中直接使用字符串拼接构建SQL语句,即便引入addslashes()或mysqli_real_escape_string()进行防护,仍然无法有效阻止SQL注入攻击。这一问题本质上不属于加固范畴,而是架构层面的结构性缺陷。

长期稳定更新的攒劲资源: >>>点此立即查看<<<
不少团队习惯编写一套“通用查询类”,底层却依然使用mysql_query()或mysqli_query()拼接字符串,只是在外层再封装一层方法名。说实话,这种做法相当于换汤不换药。真正安全的做法是:所有执行入口——例如select()、update()——内部必须调用prepare()配合execute(),并且绝对禁止开放一个能够直接拼写完整SQL的接口。
PDO或MySQLi实例,且该实例必须禁用模拟预处理:PDO::ATTR_EMULATE_PREPARES => falsewhere条件、limit值、order字段——必须通过占位符传入,不能直接在SQL字符串中插值拼接raw()、expr()、setSql()这类方法,默认就必须禁掉,或者仅允许极少数白名单内的固定语句(例如"NOW()")预处理占位符和:name只能用于数据值,不能用于标识符——像表名、列名、ORDER BY、GROUP BY这类元素都不适用。自定义类如果支持动态字段,就必须提前约定好允许范围,运行时只做匹配,不做任何转义处理。
$allowedSortFields = ['id', 'created_at', 'status'],然后用in_array($_GET['sort'], $allowedSortFields) $_GET['sort'] : 'id'进行选择$tableMap = ['user' => 'users', 'order' => 'orders']; $realTable = $tableMap[$_GET['type']] 'users';filter_var($input, FILTER_SANITIZE_STRING)处理字段名——它只管删除HTML标签,对SQL注入根本不起作用预处理不支持直接将数组绑定到IN ()这种操作。自定义类如果封装了whereIn(),就必须动态生成对应数量的,再将数组值平铺进参数列表中。
"WHERE id IN ()", [$ids]——这只会把整个数组转成字符串,最终变成IN ('Array')str_repeat(',', count($ids) - 1) . ''构造占位符串,再用array_values($ids)提取纯数值参数bind_param('i', ...),字符串数组用's',混合类型需要拆开处理有人认为“我用了filter_var($id, FILTER_VALIDATE_INT),拼接就安全了”——这实际上是一个比较常见的误解。整数校验无法防范逻辑绕过的攻击(例如传-1 OR 1=1),也无法防范字符集攻击(如宽字节截断),更无法防范业务层误用(例如把校验过的ID当用户名拼进另一个查询)。
(int)、邮箱用FILTER_VALIDATE_EMAIL、长度超限直接return false"SELECT * FROM {$table} WHERE id = " . $id这种模式,验证就形同虚设说到底,真正困难的不是写对一个prepare(),而是让整个查询类的所有分支路径都走同一套绑定机制,并且不允许有任何例外。一旦为了“兼容旧逻辑”放开一个口子——例如增加一个unsafeRawQuery()——那整套防护就归零了。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述