使用 SqlParameter 替代字符串拼接是最直接有效的防注入手段,需全程参数化、显式指定类型与长度、正确设置 CommandType、严控数据库权限并结合日志监控。

用 SqlParameter 替代字符串拼接是最直接有效的防注入手段
SQL 注入本质是把用户输入当成了 SQL 代码执行。C# 里最常见错误就是用 string.Format 或 + 拼接 SQL 字符串,比如:"SELECT * FROM Users WHERE Name = '" + userName + "'" —— 只要用户输 ' OR '1'='1,就完蛋。
正确做法是全程使用 SqlParameter,让 ADO.NET 自动处理转义和类型绑定:
var cmd = new SqlCommand("SELECT * FROM Users WHERE Id = @id AND Status = @status", conn);
cmd.Parameters.Add(new SqlParameter("@id", userId));
cmd.Parameters.Add(new SqlParameter("@status", "Active"));
- 参数名(如
@id)必须和 SQL 中一致,大小写敏感 - 不要用
cmd.Parameters.AddWithValue()处理可变长度字符串(如varchar),它可能推断出过短的长度,导致索引失效或截断;显式指定SqlDbType.VarChar和Size更稳妥 - 空值要用
DBNull.Value,不能传null
EF Core 查询也得警惕原始 SQL 和字符串插值
EF Core 默认的 LINQ 查询是安全的,但一旦用了 FromSqlRaw、ExecuteSqlRaw 或 C# 10+ 的插值字符串 $"SELECT ... {input}",风险立刻回归。
必须坚持参数化:
context.Users.FromSqlRaw("SELECT * FROM Users WHERE Email LIKE @pattern",
new SqlParameter("@pattern", $"%{searchTerm}%"));
-
FromSqlInterpolated看似支持插值,但它只对变量部分做参数化,**不能**用于表名、列名、排序字段等动态结构 - 如果真要拼接表名(比如分表场景),必须白名单校验,不能依赖正则“过滤掉危险字符”——攻击者绕过太容易
- EF Core 7+ 的
ExecuteSqlInterpolated仍不支持ORDER BY参数化,需用条件分支或枚举映射
存储过程调用不是免检区,SqlCommand.CommandType 得设对
很多人以为“用了存储过程就天然防注入”,其实错在调用方式:如果把过程名拼进 SQL 字符串,或者没设对命令类型,照样中招。
正确调用方式:
var cmd = new SqlCommand("GetUserById", conn);
cmd.CommandType = CommandType.StoredProcedure; // 关键!
cmd.Parameters.Add(new SqlParameter("@id", userId));
- 漏掉
cmd.CommandType = CommandType.StoredProcedure,ADO.NET 就当它是普通 SQL 执行,参数会被忽略 - 存储过程内部如果用了
EXEC(@sql)或sp_executesql且未参数化,外部安全也白搭 - 避免用
CREATE PROC ... AS EXEC('... ' + @input)这类写法,哪怕加了QUOTENAME()也不推荐——逻辑越简单越可靠
连接字符串和权限配置影响实际防御效果
再规范的代码,如果数据库账号权限过大或连接字符串暴露敏感信息,也会放大风险。
- 应用连接数据库的账号,**禁止**用
sa或db_owner;应按最小权限原则,只授予所需表的SELECT/INSERT/UPDATE权限 - 连接字符串里的
Integrated Security=true在 Windows 环境更安全,避免明文密码;若必须用 SQL 账号,确保密码不硬编码,走密钥管理服务(如 Azure Key Vault) - 启用数据库层面的查询日志(如 SQL Server 的
QUERY_STORE)能帮你发现异常长的、带嵌套注释或UNION SELECT的查询,这是注入尝试的典型痕迹
防注入不是某个函数调用就能一劳永逸的事。它贯穿在参数化写法、存储过程设计、权限控制、甚至日志监控里。最容易被忽略的是:把参数化当成“做了就行”,却没验证它是否真生效——比如忘了设 CommandType,或在 EF 插值里混用了非参数表达式。










