Внедрение SQL Server для процедуры с динамическим SQL - PullRequest
0 голосов
/ 06 мая 2018

Я использовал динамический SQL в своей процедуре SQL Server, я заменил все одинарные кавычки двумя одинарными кавычками перед передачей параметров в мою процедуру. Это предотвращает инъекцию SQL?

Моя процедура, как показано ниже

CREATE PROCEDURE [dbo].[SP_CM_LST_XML]  
    (@pTable VARCHAR(MAX),
     @pColumns VARCHAR(MAX),
     @pFilterAndEQ VARCHAR(MAX),
     @pFilterAndLK VARCHAR(MAX),
     @pFilterOrEQ VARCHAR(MAX),
     @pFilterOrLK VARCHAR(MAX),
     @pFilterAdditional VARCHAR(MAX),
     @pSortField VARCHAR(MAX),
     @pDirection VARCHAR(MAX),
     @pAdditionalSort VARCHAR(MAX),
     @pFromRowno INT,
     @pToRowNo INT,
     @pDeleted INT,
     @pDataType INT,
     @pCompany VARCHAR(MAX)) 
AS
     DECLARE @v_sort VARCHAR(MAX) = '';
     DECLARE @v_where VARCHAR(MAX) = '';
     DECLARE @v_whereAndEQ VARCHAR(MAX) = '';
     DECLARE @v_WhereAndLK VARCHAR(MAX) = '';
     DECLARE @v_whereOrEQ VARCHAR(MAX) = '';
     DECLARE @v_WhereOrLK VARCHAR(MAX) = '';
     DECLARE @v_deleted VARCHAR(MAX) = '';
     DECLARE @v_Company VARCHAR(MAX) = '';
     DECLARE @v_DataType VARCHAR(MAX) = '';
     DECLARE @v_sql VARCHAR(MAX) = ''; 
     DECLARE @vIndex int;

     BEGIN TRY
        DECLARE @idoc INT;
        DECLARE @Type VARCHAR(MAX) ='';
        DECLARE @Field VARCHAR(MAX) ='';
        DECLARE @Value VARCHAR(MAX) =''; 

        -- Add Filter Condition -- AND + EQUAL
        IF LEN(@pFilterAndEQ) > 35   
        BEGIN
            EXEC sp_xml_preparedocument @idoc OUTPUT, @pFilterAndEQ; 

            DECLARE CurName CURSOR FAST_FORWARD READ_ONLY FOR 
                 SELECT * 
                 FROM OPENXML (@idoc, '/data/row',1)  WITH (Type varchar(max),  Field varchar(max),  Value varchar(max))

 OPEN CurName
 FETCH NEXT FROM CurName INTO @Type, @Field, @Value
 WHILE @@FETCH_STATUS = 0
    BEGIN
        set @v_whereAndEQ = @v_whereAndEQ + ' AND UPPER(' + @Field +  ') = UPPER(''' + @Value +  ''')'; 
        FETCH NEXT FROM CurName INTO @Type, @Field, @Value
    END
 CLOSE CurName
 DEALLOCATE CurName
 END

 -- Add Filter Condition -- AND + LIKE
  if LEN(@pFilterAndLK) >35  
  BEGIN
 EXEC sp_xml_preparedocument @idoc OUTPUT, @pFilterAndLK; 
 DECLARE CurName CURSOR FAST_FORWARD READ_ONLY
 FOR SELECT * FROM OPENXML (@idoc, '/data/row',1)  WITH (Type varchar(max),  Field varchar(max),  Value varchar(max))

 OPEN CurName
 FETCH NEXT FROM CurName INTO @Type, @Field, @Value
 WHILE @@FETCH_STATUS = 0
    BEGIN
        set @v_whereAndLK = @v_whereAndLK + ' AND UPPER(' + @Field +  ') LIKE UPPER(''%' + @Value +  '%'')'; 
        FETCH NEXT FROM CurName INTO @Type, @Field, @Value
    END
 CLOSE CurName
 DEALLOCATE CurName
 END


 -- Add Filter Condition -- OR + EQUAL
  if LEN(@pFilterOrEQ) >35  
  BEGIN
 EXEC sp_xml_preparedocument @idoc OUTPUT, @pFilterOrEQ; 
 DECLARE CurName CURSOR FAST_FORWARD READ_ONLY
 FOR SELECT * FROM OPENXML (@idoc, '/data/row',1)  WITH (Type varchar(max),  Field varchar(max),  Value varchar(max))

 set @vIndex =1;
 OPEN CurName
 FETCH NEXT FROM CurName INTO @Type, @Field, @Value
 WHILE @@FETCH_STATUS = 0
    BEGIN  
        if @vIndex = 1  
          set @v_WhereOrEQ = @v_WhereOrEQ + ' AND (UPPER(' + @Field + ') = UPPER(''' + @Value + ''')';
        else
          set @v_WhereOrEQ = @v_WhereOrEQ + ' OR UPPER(' + @Field + ') = UPPER(''' + @Value + ''')';

        set @vIndex = @vIndex + 1;
        FETCH NEXT FROM CurName INTO @Type, @Field, @Value
    END
 CLOSE CurName
 DEALLOCATE CurName

 if LEN(@v_whereOrEQ) > 0  
    set @v_whereOrEQ = @v_whereOrEQ + ') ';
 END   

 -- Add Filter Condition -- OR + LIKE
  if LEN(@pFilterOrLK) >35  
  BEGIN
 EXEC sp_xml_preparedocument @idoc OUTPUT, @pFilterOrLK; 
 DECLARE CurName CURSOR FAST_FORWARD READ_ONLY
 FOR SELECT * FROM OPENXML (@idoc, '/data/row',1)  WITH (Type varchar(max),  Field varchar(max),  Value varchar(max))

set @vIndex =1;
 OPEN CurName
 FETCH NEXT FROM CurName INTO @Type, @Field, @Value
 WHILE @@FETCH_STATUS = 0
    BEGIN 
        if @vIndex = 1  
          set @v_WhereOrLK = @v_WhereOrLK + ' AND (UPPER(' + @Field + ') LIKE UPPER(''%' + @Value + '%'')';
        else
          set @v_WhereOrLK = @v_WhereOrLK + ' OR UPPER(' + @Field + ') LIKE UPPER(''%' + @Value + '%'')';

        set @vIndex = @vIndex + 1;
        FETCH NEXT FROM CurName INTO @Type, @Field, @Value
    END
 CLOSE CurName
 DEALLOCATE CurName

if LEN(@v_WhereOrLK) > 0  
    set @v_WhereOrLK = @v_WhereOrLK + ') ';
END


 IF @pDeleted = 0  
    set @v_deleted = @v_deleted + ' AND REC_TYPE <> ''5'' ';


    set @v_DataType = @v_DataType + ' AND DATA_TYPE = ''' + + ''' ';

  IF @pCompany = '0'  
    set @v_Company =  ' AND Created_Comp = ''' +  @pCompany + ''' ';

 set @v_where =  @v_whereAndEQ + ' ' + @v_WhereAndLK + ' ' + @v_whereOrEQ + ' ' + @v_WhereOrLK + ' ';


 if @pDirection = '1'
     set @v_sort = ' desc ';
     else
     set @v_sort = ' asc ';


 SET @v_sql = 'SELECT * FROM (select row_number() OVER (order by ' + @pSortField + ' ' + @v_sort + ' ' + Convert(varchar(max),@pAdditionalSort)  + ') AS DefaultRowIndex, COUNT(*) OVER () AS TotalFiltered, TC.TotalRecord, A.' + @pColumns + ' from ' + @pTable + ' A CROSS APPLY (SELECT  count(*) as TotalRecord FROM ' + @pTable + ' where 1 = 1 ' + @v_deleted + ' ' + @v_Company + ') TC WHERE 1 = 1 ' + @v_deleted + ' ' + @v_Company + ' ' + @v_where + @pFilterAdditional + ') TB WHERE TB.DefaultRowIndex >= ' + Convert(varchar(max),@pFromRowno) + ' and TB.DefaultRowIndex <= ' + Convert(varchar(max),@pToRowNo);

    EXEC(@v_sql);


END TRY
BEGIN CATCH

END CATCH;

Я использовал строку XML для параметров @pFilterAndEQ, @pFilterAndLK, @pFilterOrEQ и @pFilterOrEQ для обработки столбца динамической таблицы. Параметры как ниже.

<?xml version='1.0' encoding='utf-8' ?><data><row Type="String" Field="Email" Value="test@test.com" /></data>
...