flawopen.com/JavaScript 中的 SQL 注入/Prisma
Prisma $queryRaw 能防止 SQL 注入吗?
参考指南
简短回答
可以把查询参数想成 SQL 表单中封装好的值栏:数据库将其视为数据,而不是语法。$queryRaw 的 tagged template 会绑定插值的值。单独传入占位符和参数时,$queryRawUnsafe 也能绑定值;把不可信文本拼接进 SQL 才会带来风险。两种方法都不能参数化表名或列名。
不安全 — 将输入拼接进 SQL
const userId = request.query.userId;
const query =
`SELECT id FROM users WHERE id = ${userId}`;
const rows = await prisma.$queryRawUnsafe(query);
加固 — 绑定值,并用白名单限定 SQL 结构
const rows = await prisma.$queryRaw`
SELECT id FROM users WHERE id = ${userId}
`;
// PostgreSQL example: $1 binds data, not an identifier.
const columns = { name: 'name', created: 'created_at' } as const;
const column = columns[requestedSort as keyof typeof columns] ?? 'created_at';
const pageSize = 25;
const sortedRows = await prisma.$queryRawUnsafe(
`SELECT id FROM users ORDER BY ${column} LIMIT $1`,
pageSize
);
// The selected SQL structure comes from a fixed map.
Prisma 参数能做什么 — 不能做什么
使用 $queryRaw 时应直接调用 tagged template:每个插值值都会成为数据库参数。不要先拼出 SQL 字符串再把它作为唯一参数传入。Prisma 也支持在 $queryRawUnsafe(query, ...values) 中使用占位符来绑定值,但 SQL 文本本身仍必须可信。参数代表数据值,不能代表标识符、运算符或 SQL 片段。可选列应映射到应用代码中的固定白名单。对于许多需要类型安全的 raw 查询,Prisma 推荐使用 TypedSQL。
如何审查 Prisma raw 查询
grep -rn "\$queryRawUnsafe\|\$executeRawUnsafe" --include="*.ts" --include="*.js" .常见问题
为什么还要提供 $queryRawUnsafe?
它接受 raw SQL 字符串,也支持单独传参的占位符。其灵活性容易导致不安全的字符串拼接,因此要同时检查 SQL 文本和参数。它不会让动态标识符变安全;标识符应从固定白名单中选择。