laravel 10 原生 db 查询必须手动参数绑定防 sql 注入,db::select() 等方法及 whereraw() 等 raw 方法均需显式传绑定数组;标识符(表名、字段名等)须白名单校验;优先使用 query builder 自动参数化方法。

只要用对方法,Laravel 10 的 DB 原生查询本身不自带防护,必须手动绑定参数——否则用户输入直接拼进 SQL 字符串,立刻触发 SQL 注入。
DB::select()、DB::update() 等原生方法必须显式绑定
这些方法绕过 Query Builder 的自动参数化机制,完全依赖你传参方式。不绑定 = 裸奔。
-
错误写法(高危):
DB::select("SELECT * FROM users WHERE id = " . $id)或DB::update("UPDATE posts SET title = '" . $title . "' WHERE id = " . $id) -
正确写法(位置占位):
DB::select("SELECT * FROM users WHERE id = ?", [$id]) -
正确写法(命名绑定):
DB::select("SELECT * FROM users WHERE id = :id", ['id' => $id]) - 所有
DB::开头的原生执行方法(select、insert、update、delete、statement)都适用同一规则
所有 Raw 方法必须带绑定数组参数
whereRaw()、selectRaw()、orderByRaw()、havingRaw()、groupByRaw() 这些方法默认不自动绑定。只要 SQL 字符串里含用户输入,第二个参数(绑定数组)就不可省略。
-
错误写法:
->whereRaw("name LIKE '%$keyword%'")或->orderByRaw($request->input('sort')) -
安全写法(值绑定):
->whereRaw("name LIKE ?", ["%{$keyword}%"]) -
安全写法(标识符禁止绑定):字段名、排序方向等不能用 ? 占位,例如
->orderByRaw($sortField . ' ' . $sortDir)中的$sortField必须白名单校验
表名、列名、排序字段等标识符必须白名单硬校验
PDO 预处理只支持绑定“值”,不支持绑定“标识符”(如表名、列名、GROUP BY 字段)。任何将用户输入拼进这些位置的操作,都是注入入口。
-
危险场景:
DB::table($request->table)、->select("col_{$suffix}")、->orderBy($request->field) -
推荐做法一(请求验证):
$request->validate(['table' => 'required|in:users,posts,comments']) -
推荐做法二(运行时校验):
if (!in_array($field, ['id', 'name', 'created_at'], true)) { abort(400); } - 不要仅靠
(int)$id或strip_tags()—— 攻击者可构造有效 payload 绕过,比如用于缓存键或日志拼接时仍会出问题
优先使用标准 Query Builder 方法,少写 Raw
绝大多数业务场景无需 Raw。用对 where()、whereIn()、orderBy()、select() 等方法,底层自动走 PDO 预处理,天然防注入。
-
User::where('email', $request->email)->first()—— 安全,哪怕$request->email是"admin' -- " -
DB::table('orders')->whereIn('status', $statuses)—— 数组也安全,框架自动生成IN (?, ?, ?) -
->where('title', 'like', "%{$q}%")—— 模糊匹配同样参数化,% 是 PHP 拼接,$q仍是绑定值 - 能不用
whereRaw()就不用;能用where()实现,就别为省一行代码引入风险











