我使用Devexpress Grid为最终用户显示我的结果。
由于我使用远程模式,我应该根据网格过滤器在服务器上过滤我自己的结果。
我做了自定义的JS开关case,使SQL的条件基于过滤器的结果,像这样:
let whereClause = '';
if (loadOptions['filter']) {
const rawFilter = loadOptions['filter'];
let filters = null;
if (_.isArray(rawFilter[0])) {
filters = _.map(rawFilter, (item) => {
if (_.isArray(item)) {
if (!_.isNumber(item[2])) {
switch (item[1]) {
case 'contains':
return `(${item[0]} LIKE N'%${item[2]}%')`;
case 'notcontains':
return `(${item[0]} NOT LIKE N'%${item[2]}%')`;
case 'startswith':
return `(${item[0]} LIKE N'${item[2]}%')`;
case 'endswith':
return `(${item[0]} LIKE N'%${item[2]}')`;
default:
return `(${item[0]} ${item[1]} N'${item[2]}')`;
}
}
else {
return `(${item[0]} ${item[1]} ${item[2]})`;
}
}
else {
return item;
}
});
whereClause = _.join(filters, ' ');
}
}
然后传递whereClause给控制器,如:"(columna like N' abc ')"
之后,像这样在存储过程中使用它(作为SearchParam传递):
CREATE OR ALTER PROCEDURE GetTestResult
@Skip INT = 0,
@Take INT = 400000,
@SearchParam NVARCHAR(MAX) = null
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sqlCommand NVARCHAR(MAX)
DECLARE @sqlCommandPagination NVARCHAR(MAX)
DECLARE @sqlCommandFinall NVARCHAR(MAX)
SET @sqlCommand = 'SELECT ColomnA,ColomnB,ColomnC FROM dbo.TestTable '
SET @sqlCommandPagination = ' ORDER BY ColomnA asc OFFSET ' + CAST(@Skip as varchar(500)) +
' ROWS FETCH NEXT ' + CAST(@Take as varchar(500)) + ' ROWS ONLY;'
If( @SearchParam <> '' AND @SearchParam IS NOT NULL )
Set @sqlCommandFinall = @sqlCommand + ' Where ' + @SearchParam + @sqlCommandPagination;
If( @SearchParam = '' OR @SearchParam IS NULL )
Set @sqlCommandFinall = @sqlCommand + @sqlCommandPagination;
Execute SP_ExecuteSQL @sqlCommandFinall;
END;
GO
是否有办法使这个方法Sql注入证明?
我使用DapperSqlMapper查询函数从c#调用我的sp .
不是这样设计的。或者至少在没有仔细解析语句,然后利用参数化值和/或积极验证组件的情况下是不会这样做的。这样做比仅仅传递组件要复杂得多,也容易出错。
在当前的设计中,在where或order by中注入SQL是微不足道的。您应该将其分解为组件,传递这些组件并在后端验证它们。因此,与其传递ColomnA like N'ABC'
(sic),不如分别传递ColomnA
(sic)和ABC
,并对这些值使用参数化查询(绑定它们)。
在第二种情况下,许多数据库不允许按值参数化顺序,因此在这种情况下,您应该确保使用正验证。