一聚教程网:一个值得你收藏的教程网站

热门教程

在.NET中如何使用Entity Framework防范SQL注入

时间:2026-07-12 09:35:45 编辑:袖梨 来源:一聚教程网

EF Core 不自动防SQL注入,FromSqlRaw和ExecuteSqlRaw必须手动参数化;FromSqlInterpolated仅安全处理纯变量插值,表名列名等结构部分须用白名单校验。

EF Core 本身不自动防注入,安全完全取决于你用哪条 API、怎么传参——FromSqlRawExecuteSqlRaw 默认就是裸奔状态,不手动参数化等于把数据库钥匙直接交给用户。

什么时候必须用参数化?FromSqlRawExecuteSqlRaw 的坑

这两个方法不做任何字符串解析或转义,只负责把传进去的字符串原样发给数据库驱动。哪怕只拼一个字段值,只要用了 +$"" 插入用户输入,就立刻破防。

  • FromSqlRaw($"SELECT * FROM Users WHERE Name = '{name}'") → 危险,C# 层已拼接完成,'admin' OR 1=1 -- 直接进 SQL
  • FromSqlRaw("SELECT * FROM Users WHERE Name = " + name) → 同样危险,字符串拼接早于 EF 执行
  • FromSqlRaw("WHERE Status = {0}", "Active") → 安全,EF 将 {0} 视为参数占位符,走绑定机制
  • FromSqlRaw("WHERE Name = @name", new SqlParameter("@name", name)) → 安全,显式构造参数对象

FromSqlInterpolated 看似省事,但有硬限制

它确实能自动参数化插值变量,但只认纯变量引用,不处理表达式或拼接逻辑。

  • context.Users.FromSqlInterpolated($"SELECT * FROM Users WHERE Name = {name}") → 安全
  • context.Users.FromSqlInterpolated($"SELECT * FROM Users WHERE CreatedAt > {DateTime.UtcNow.AddDays(-7)}") → 安全
  • context.Users.FromSqlInterpolated($"SELECT * FROM Users WHERE Name LIKE {name + "%"}") → 危险,name + "%" 是 C# 表达式,结果整体当参数,语义错乱
  • context.Users.FromSqlInterpolated($"SELECT * FROM Users WHERE {whereClause}") → 完全无效,whereClause 是字符串变量,会被整个当参数值,WHERE 条件消失

表名、列名、ORDER BY 这类结构部分不能参数化

数据库引擎不支持参数化标识符(identifier),FromSqlRaw("SELECT * FROM {0}", tableName) 在语法上就非法,EF 也不会帮你校验或转义。

  • 动态表名/列名必须走白名单:比如只允许 new[] { "Users", "Orders", "Products" } 中的值
  • 排序字段和方向必须显式判断:if (!new[] { "Name", "Email", "CreatedAt" }.Contains(sortField)) throw ...if (sortDir != "ASC" && sortDir != "DESC") throw ...
  • 禁止用 string.ConcatStringBuilderReplace “过滤关键词”来糊弄——"or" 被删了,"oR" 或换行绕过照样生效

真正麻烦的不是写对那几行参数化代码,而是得时刻分清“数据”和“结构”:值可以参数化,SQL 骨架必须靠白名单兜底。漏掉任何一个动态拼接点,整条链路就失效。

热门栏目