跳转到主内容
极星编程网:以代码为星,赴技术山海!

.NET Core项目怎么修复SQL注入_使用Entity Framework Core参数化

EF Core 的 LINQ 查询(如 Where、Find)默认参数化,防 SQL 注入;FromSqlRaw/ExecuteSqlRaw 若字符串插值则危险,须用参数化或白名单校验;动态查询应构建表达式树而非拼接 SQL。 直接用
EF Core
做查询,只要不手拼 SQL 字符串,就基本不会出 SQL 注入问题。但很多人误以为“用了 EF 就安全了”,结果在
FromSqlRaw
、
ExecuteSqlRaw
或字符串插值里翻车。 为什么
Where
和
Find
是安全的 EF Core 的 LINQ 查询(比如
context.Users.Where(u => u.Name == name)
)默认走参数化执行:SQL 语句模板和参数值分离,数据库引擎只把变量当数据处理,不解析为语法结构。 底层生成类似
SELECT * FROM Users WHERE Name = @p0
,
@p0
是绑定的参数,不是字符串拼接 即使
name
是
"admin' OR '1'='1"
,也会被当作完整字符串值传入,不会破坏 SQL 结构 所有
Find
、
Single
、
First
及带 lambda 的
Where
都自动参数化,无需额外操作
FromSqlRaw
和
ExecuteSqlRaw
是高危区 这两个方法明确告诉你“我要写原生 SQL”,一旦用
$"..."
插值或
string.Format
拼接用户输入,立刻回归手写 SQL 的风险等级。 ❌ 危险写法:
context.Users.FromSqlRaw($"SELECT * FROM Users WHERE Name = '{name}'")
✅ 正确写法:
context.Users.FromSqlRaw("SELECT * FROM Users WHERE Name = {0}", name)
(位置参数) ✅ 更推荐:
context.Users.FromSqlRaw("SELECT * FROM Users WHERE Name = @name", new SqlParameter("@name", name))
注意:
FromSqlInterpolated
看似用
$
,但它会自动参数化插值内容,是安全的 —— 但仅限于直接插变量,不能插表达式或拼接逻辑 动态查询构建别绕过 EF 的参数化机制 常见需求如“按多个字段模糊搜索”,容易写出
if
堆叠 + 字符串拼接的 SQL。这不是 EF 的错,是你主动放弃了它的保护。 防SQL注入的php类库 防SQL注入的php类库 下载 ❌ 错误思路:用
StringBuilder
拼
WHERE
条件,最后喂给
FromSqlRaw
✅ 推荐做法:用 LINQ 动态构建表达式树,例如用
ExpressionVisitor
或第三方库如
Linq.Dynamic.Core
,保持整个链路在 EF 参数化体系内 如果必须用原生 SQL,所有用户可控字段(如搜索关键词、排序字段名)必须严格白名单校验,不能仅靠参数化 —— 参数化防不住列名、表名、
ORDER BY
子句注入 连接字符串和上下文配置本身也要防注入 很少有人想到,
ConnectionString
如果来自配置中心或环境变量,且未做校验,也可能被污染 —— 特别是启用了
Connect Timeout
、
Application Name
这类可被攻击者控制的参数时。 EF Core 的
UseSqlServer
不会对连接字符串内容做注入检查,它原样交给
SqlClient
确保连接字符串来源可信;若需动态构造,只拼接已知安全的部分(如服务器地址、数据库名),禁用用户可触达的参数项 另外,
EnableRetryOnFailure
等策略配置不影响注入防护,但错误地启用它可能掩盖真实异常,反而让注入点更难被发现 最易被忽略的一点:ORM 安全性完全取决于你调用它的姿势。EF Core 不会阻止你写
FromSqlRaw($"...{userInput}...")
,就像刀不会阻止你割自己手指 —— 它只提供安全的握柄方式,而你得真握住它。

相关文章