Blazor应用本身不执行SQL查询,SQL注入风险存在于后端数据访问层;必须使用参数化查询(如EF Core的Where或FromSqlInterpolated),禁用字符串拼接SQL,配合输入验证与安全配置连接字符串。

Blazor 服务端应用本身不直接执行 SQL 查询,SQL 注入风险不出现在 Blazor 组件层,而是在你调用后端数据访问逻辑(如 EF Core、Dapper 或 ADO.NET)时才真正存在。因此,“在 Blazor 中防 SQL 注入”本质是:确保服务端控制器、API 方法或仓储层使用了安全的数据访问方式。
Blazor 组件里写 SqlCommand 就已经错了
常见错误现象:有人在 @code 块里拼接 SQL 字符串,比如:
var sql = $"SELECT * FROM Users WHERE Name = '{userName}'";这在 Blazor Server 中依然危险——只要该代码最终运行在服务端(它确实会),且未加防护,就可能被利用。
正确做法是:Blazor 组件只负责接收和传递用户输入,所有数据库操作必须委托给受控的服务层,并满足以下条件:
- 绝不使用字符串插值或
string.Format拼接 SQL - 不手动转义输入(如
Replace("'", "''")),这不可靠 - 不信任前端传来的任何值——包括隐藏字段、
input的value、甚至id属性
EF Core 查询必须用参数化方式
EF Core 默认使用参数化查询,但某些写法会绕过它,导致漏洞:
- ✅ 安全:
context.Users.Where(u => u.Email == email)—— EF 自动转为带参数的 SQL - ❌ 危险:
context.Users.FromSqlRaw($"SELECT * FROM Users WHERE Email = '{email}'")—— 直接拼接,高危 - ✅ 替代危险写法:
context.Users.FromSqlRaw("SELECT * FROM Users WHERE Email = {0}", email) - ✅ 更推荐:
context.Users.FromSqlInterpolated($"SELECT * FROM Users WHERE Email = {email}")
注意:FromSqlRaw 和 ExecuteSqlRaw 是 EF Core 中最易出错的 API,除非绝对必要,否则避免使用;若必须用,只接受参数占位符形式,绝不接受字符串拼接。
验证 + 清理不能替代参数化,但必须共存
参数化查询解决的是“执行时注入”,而输入验证解决的是“业务合理性”。两者不是二选一:
- 即使用了 EF Core 参数化,也应配合
[EmailAddress]、[Range]等数据注解做模型验证(通过DataAnnotationsValidator在前端提示) - 服务端控制器仍需调用
ModelState.IsValid再执行数据库操作——防止绕过前端直接 POST 恶意数据 - 对自由文本字段(如评论、描述),可额外使用
HtmlEncoder.Default.Encode()防止 XSS,但这和 SQL 注入无关,别混淆
关键点:验证失败时,返回 BadRequest(ModelState),而不是尝试“清理后入库”。
别把数据库连接字符串或凭据放进 Blazor 组件
虽然和 SQL 注入无直接关系,但这是常被忽略的关联风险:
- Blazor Server 组件运行在服务端,但其状态通过 SignalR 推送到浏览器,
@inject的服务实例是服务端对象,**不等于你可以把连接字符串写死在.razor文件里** - 连接字符串必须由 DI 容器注入(如
IConfiguration或专用IDbConnectionStringProvider),且绝不能出现在组件的@code块中作为字面量 - 如果用了自定义仓储并手动 new
SqlConnection,务必从IConfiguration读取连接字符串,并确认未被前端可控参数污染(例如没把用户传的serverName拼进连接字符串)
真正的防线永远在数据访问层——Blazor 只是输入的入口,不是执行 SQL 的地方。盯紧你调用 DbContext 或 DbCommand 的那几行代码,比纠结组件怎么写更重要。

















