我是中文测试',并试图找到使用Entity Framework Core
来存储过程的"最安全"的方法。您会认为这很明显,但请继续阅读。
背景
使用此文档使用RAW SQL并阅读了.NET Core 2.0中的新内容2.0我的初始代码使用了字符串插值(在" What what new new"文档中显示为安全)。
但是,笔测试成功地管理了SQL注射攻击。
有问题的代码示例:
dbResults = _datacontext.Blogs.FromSql($"myStoredProcedure @parmeter1 = {parmeter1String}");
所以,我更改了使用参数的代码,但是它们也违反了:
dbResults = _datacontext.Blogs.FromSql("myStoredProcedure @parmeter1 = {0}", parmeter1String);
他们打破了这个(尽管也许我还不够清洁 - 至少我停止了exec
):
dbResults = _datacontext.Blogs.FromSql("myStoredProcedure @parmeter1 = {0}", parmeter1String.ToCleanedSqlString());
那么使用SQLPARAMETER的答案(以上任何文档/示例中未显示)?
dbResults = _datacontext.Blogs.FromSql("myStoredProcedure @parmeter1 = {0}", new SqlParameter("@parmeter1", parmeter1String));
还是有更好的方法?
请感谢一些确定的指导。
编辑以下评论:
重要的添加:存储过程确实执行动态SQL,但是该过程不在我的应用程序中,我无法控制它。我必须称之为。
以下评论,我认为我应该添加一个结论(谢谢@Alexk通过评论)。
如果使用非参数化动态SQL编写存储过程,则实体框架不可能保护它。这不是实体框架的错(通常,这是非常擅长SQL保护)。
如果您发现自己处于类似情况,则应使用参数化动态SQL重写存储的过程。可以在这里找到一个很好的解释。
详细说明。
实体框架无法像这样保护SQL:
CREATE PROCEDURE search_orders @custid nchar(5) = NULL,
@shipname nvarchar(40) = NULL AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ' SELECT OrderID, OrderDate, CustomerID, ShipName ' +
' FROM dbo.Orders WHERE 1 = 1 '
IF @custid IS NOT NULL
SELECT @sql = @sql + ' AND CustomerID LIKE ''' + @custid + ''''
IF @shipname IS NOT NULL
SELECT @sql = @sql + ' AND ShipName LIKE ''' + @shipname + ''''
EXEC(@sql)
但这将是安全的:
CREATE PROCEDURE search_orders @custid nchar(5) = NULL,
@shipname nvarchar(40) = NULL AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ' SELECT OrderID, OrderDate, CustomerID, ShipName ' +
' FROM dbo.Orders WHERE 1 = 1 '
IF @custid IS NOT NULL
SELECT @sql = @sql + ' AND CustomerID LIKE @custid '
IF @shipname IS NOT NULL
SELECT @sql = @sql + ' AND ShipName LIKE @shipname '
EXEC sp_executesql @sql, N'@custid nchar(5), @shipname nvarchar(40)',
@custid, @shipname
据我所知,该问题中的任何代码示例都将是有效的"安全" EF代码(尽管扩展方法上的额外工作将是剩余的要求)。
update
之后,我联系了Microsoft并创建了一个PR,其基础已被接受。现在,官方文档上的警告消息已更加详细,希望减少某人遇到相同问题的机会。