0

莫名其妙的问题。我正在使用 SQL 全文搜索,我最初使用 string.format 直接执行查询来创建它们。以下是 sql profiler 生成的 SQL 字符串示例:

SELECT TOP 100 * FROM CatName WHERE CONTAINS(FullName, '"Spotty" AND "Cat"')

效果很好。

但是,由于我是通过获取用户输入并将其放入来创建该字符串,因此我们存在 SQL 注入的风险。因此,我创建了参数化它的 SQL。

在分析器中执行的 SQL 是这样的:

exec sp_executesql N'SELECT TOP 100 * FROM CatName WHERE CONTAINS(FullName, ''"@p1" AND "@p2"'')',N'@p1 nvarchar(6),@p2 nvarchar(3)',@p1=N'Spotty',@p2=N'Cat'

据我所知,这是一样的。但是,第二个查询不返回任何结果。

我怀疑这与替换参数的方式有关,因为全文搜索查询在每个参数的单引号内使用双引号,但我完全不知所措。

我需要一种方法来清理输入以防止 SQL 注入,这就是我在互联网上能找到的全部内容。

有任何想法吗?

有和没有参数化的代码:

string _fullTextSearchQuery = "SELECT TOP {0} * FROM {1} WHERE CONTAINS({2}, '{3}')";

var searchText = @"""" + searchText.Replace(" ", @""" AND """) + @"""";

string[] unorderedWords = searchText.Split(' ');

searchText = "";

int unorderedIndex = 1;
foreach (string word in unorderedWords)
{
    searchText += @"""" + "@p" + unorderedIndex + @""" AND ";
    parameters.Add(new SqlParameter("p" + unorderedIndex, word));
    unorderedIndex++;
}

searchText = searchText.Substring(0, searchText.Length - 5);

无论哪种方式,然后创建最终字符串:

string textSearchQuery = string.Format(
    _fullTextSearchQuery,
    top,
    tableName,
    columnName,
    searchText);

return catContext.SqlQuery<T>(textSearchQuery, parameters.ToArray());

因为有点乱,这里就是执行前生成的字符串:

非参数化:

"SELECT TOP 100 * FROM CatName WHERE CONTAINS(FullName, '\"Spotty\" AND \"Cat\"')"

参数化:

"SELECT TOP 100 * FROM CatName WHERE CONTAINS(FullName, '\"@p1\" AND \"@p2\"')"

参数数组是正确的,没有杂项。引用它与您期望的完全一样。

4

1 回答 1

0

解决方案非常简单,重要的是要将传递给 CONTAINS 的值视为单个值而不是多个值。

所以在我传入“Spotty”和“Cat”并假设这是2个参数的地方,实际上整个字符串是一个参数。

所以这是一个简单的案例"SELECT TOP {0} * FROM {1} WHERE CONTAINS({2}, @P1)";

在哪里@P1 = "'\"Spotty\" AND \"Cat\"'"

于 2013-10-23T13:55:22.303 回答