Sql server 当t-sql动态代码作为过滤器使用sp_executesql时,保护它的最佳方法是什么

Sql server 当t-sql动态代码作为过滤器使用sp_executesql时,保护它的最佳方法是什么,sql-server,tsql,sql-injection,dynamic-sql,Sql Server,Tsql,Sql Injection,Dynamic Sql,我正在制作一个接受动态过滤的存储过程,问题是我需要尽可能地保持它的灵活性 ALTER PROCEDURE astp_test @WhereClause NVARCHAR(max) = NULL AS DECLARE @FilteredResults AS TABLE (testId int, testfield datetime2) DECLARE @sql AS NVARCHAR(MAX) = N'SELECT testId ,

我正在制作一个接受动态过滤的存储过程,问题是我需要尽可能地保持它的灵活性

ALTER PROCEDURE astp_test
    @WhereClause NVARCHAR(max) = NULL
AS

DECLARE @FilteredResults AS TABLE (testId int, testfield datetime2)
DECLARE @sql AS NVARCHAR(MAX) = N'SELECT testId ,                               testfield 
                                        FROM aviw_test
                                        WHERE IsOpen = 1 AND IsLatesInsert = 1
                                            AND testStepNo = 7
                                            AND test2 IS NULL
                                            AND (testfielddate IS NULL OR testfielddate2 < GETUTCDATE()) 
                                            AND Domain IN (SELECT Domain FROM project WITH (NOLOCK) WHERE Status = ''Active'')' + 
    CASE WHEN @WhereClause IS NOT NULL 
        THEN  N' AND ' + @WhereClause ELSE N''
    END

INSERT INTO @FilteredResults
    EXEC sys.sp_executesql @stmt = @sql;
我希望以这种方式保护@WhereClause输入,因为有一些复选框发送如下内容:testDatePick='2019-10-10'和testStage='InProgress'和testArea='London'。那么什么是最好的方法呢?

请尝试下面的方法

    ALTER PROCEDURE astp_test
        @WhereClause NVARCHAR(max) = NULL
    AS

    DECLARE @FilteredResults AS TABLE (testId int, testfield datetime2)
    DECLARE @sql AS NVARCHAR(MAX) = N'SELECT testId ,                               testfield 
                                            FROM aviw_test
                                            WHERE IsOpen = 1 AND IsLatesInsert = 1
                                                AND testStepNo = 7
                                                AND test2 IS NULL
                                                AND (testfielddate IS NULL OR testfielddate2 < GETUTCDATE()) 
                                                AND Domain IN (SELECT Domain FROM project WITH (NOLOCK) WHERE Status = ''Active'')' 

if @WhereClause is not null
set @sql=@sql + 'AND ' + @WhereClause

    INSERT INTO @FilteredResults
        EXEC sys.sp_executesql @stmt = @sql;
如果您有任何问题,请告诉我


谢谢

最好的方法是不要使用动态sql。@where子句包含什么?为什么不使用ORM生成一个好的SQL查询?事实上,为什么不将@sql转换成一个视图并在其上编写一个简单的查询呢?带NOLOCK的PS不会使缓慢的查询运行得更快,它会在获取额外锁的同时读取脏数据。为了使这个子查询运行得更快,请在Status、Domain上添加一个索引,并可能使用SNAPSHOT isolationI不同意@PanagiotisKanavos。但是,最好的方法是使用QUOTENAME安全地注入对象名,并对语句进行参数化。但是,在何处注入一个WHERE是完全错误的想法,因为你永远无法保证它的安全;您必须信任客户端,因为在T-SQL中解析T-SQL是不可能的。在这种情况下,最好将查询逻辑集中在客户机中,这样您就有一个地方来验证它,并为查询中不会更改的部分声明一个视图。我还建议阅读大量关于不同的、更安全的动态搜索方法的背景信息,以及与每种方法相关的陷阱。我不同意这种笼统的说法,最好的方法是不要使用动态sql@PanagiotisKanavos。该评论自发布以来一直在编辑,但仅仅说动态SQL不好肯定是错误的。写得不好的动态SQL是不好的,但写得好、安全的动态SQL是好的;当然,它也有使用的时间。为了修复它的安全性,@pixe您需要删除该参数@WhereClause,并将其替换为需要比较的每列1个参数。这将需要对数据库和应用程序进行更改。这是一项要求。如果不这样做,就无法保证安全。如果您不能做到这一点,我强烈建议您删除该功能。