为了防止sql注入,我试图使用参数化查询。但是我不清楚我是否应该只调用where子句或查询的其他部分。例如,我正在尝试改进以下查询:
string strQ = @";WITH lstTable as (
SELECT ROW_NUMBER() OVER(ORDER BY " + sort + @") AS RowNum, *
FROM (
SELECT *
FROM SystemMessage
WHERE Deleted = 0 ";`
此查询正在网格中使用,并根据用户的选择,它将按列名称排序。我需要使用paramaterize' sort'在这种情况下?
答案 0 :(得分:4)
您是正确的,您不能直接使用参数用于此用例。但是,如果您需要使用参数,则取决于sort
的填充方式。
如果它是硬编码的列名列表,并且用户只选择列表中的哪些索引将被选中,则无需担心参数化,用户在查询中没有直接输入所以他们不能把代码注入其中。
如果用户直接提供列名,则必须在传入之前清理用户输入,这样做的方法是使用sql函数QUOTENAME
来清理输入。
string strQ = @"
declare @query nvarchar(max)
set @query = ';WITH lstTable as (
SELECT ROW_NUMBER() OVER(ORDER BY' + QUOTENAME(@sortColumn) + ') AS RowNum, *
FROM (
SELECT *
FROM SystemMessage
WHERE Deleted = 0 '
exec sp_executesql @query";
这将会传递给@sortColumn
的任何字符串,它会正确地将[ ]
包裹在该字符串值周围。然后,它在动态生成的字符串中使用该excaped值,并使用sp_executesql
运行该值。
一个重要的注意事项,此示例目前仅适用于单个列名称,您需要为要添加到查询中的每列添加QUOTENAME
和新参数。如果您尝试传入FirstName, LastName
,则会变为
;WITH lstTable as (
SELECT ROW_NUMBER() OVER(ORDER BY [FirstName, LastName]) AS RowNum, *
FROM (
SELECT *
FROM SystemMessage
WHERE Deleted = 0
执行时会尝试查找名为“[FirstName, LastName]
”的列,但会失败。