如何防止SQL注入利用存储过程_确保存储过程不拼字符串
必须用sp_executesql代替EXEC实现参数化查询严格声明参数类型与长度对表名列名等动态部分采用白名单校验并对输入参数做强类型声明和范围检查。存储过程中用 sp_executesql 代替 EXEC 才安全直接拼接字符串再执行哪怕在存储过程里照样被注入。SQL Server 的 EXEC 会把整个字符串当命令解析参数没隔离——sql SELECT * FROM users WHERE id id 这种写法传入 id 1; DROP TABLE users; -- 就完蛋。必须改用 sp_executesql它支持真正的参数化查询SQL 引擎会在编译阶段就区分代码和数据DECLARE sql NVARCHAR(MAX) NSELECT * FROM users WHERE status status AND created_after since;EXEC sp_executesql sql, Nstatus TINYINT, since DATETIME, status 1, since 2024-01-01;sp_executesql 的第二个参数是参数定义字符串必须显式声明类型和长度比如 NVARCHAR(50)不能只写 NVARCHAR第三个及之后的参数才是实际值顺序和定义严格对应别图省事把变量名和参数名搞混定义里写 status调用时也得传 status ...不是传变量值本身如果动态部分涉及表名或列名无法参数化必须走白名单校验不能靠 REPLACE 或正则过滤所有用户输入进存储过程前先做类型强转和范围检查即使用了 sp_executesql如果参数本身是弱类型或未校验攻击者仍可能绕过。比如把 id 设为 INT 类型但调用时传入 1 OR 11SQL Server 会隐式转成 1——看似安全实则掩盖了上游传参不规范的问题。存储过程参数声明必须用具体、窄的类型user_id INT而不是 user_id SQL_VARIANT 或宽泛的 NVARCHAR(MAX)对数字类参数加 IF user_id 1 OR user_id 999999 RETURN 这类硬约束对字符串类参数如用户名用 LEN(name) 0 AND LEN(name) 50 AND name NOT LIKE %[^a-zA-Z0-9_]% 控制内容范围避免在存储过程里做 CAST 或 CONVERT 转换用户输入——转换失败会报错但成功转换后可能已失真禁止在存储过程中拼接对象名表名、列名、排序字段表名、列名、ORDER BY 字段这些语法成分SQL Server 不允许用参数占位硬拼就是高危操作。见过太多人写 SET sql SELECT * FROM table_name再加一层 QUOTENAME(table_name) 就以为万事大吉——但 QUOTENAME 只防单引号防不了 ]; DROP TABLE x; -- 这种结尾注入。 唱鸭 音乐创作全流程的AI自动作曲工具集 AI 辅助作词、AI 自动作曲、编曲、混音于一体