令人困惑的问题。我正在使用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\"')"
参数数组正确,没有misc。引用它就像你期望的那样。
答案 0 :(得分:0)
解决这个问题非常简单,重要的是要将传递给CONTAINS的值作为单个值而不是多个值来考虑。
所以,我在“Spotty”和“Cat”中传递,并假设这是2个参数,实际上整个字符串是一个参数。
所以这是一个"SELECT TOP {0} * FROM {1} WHERE CONTAINS({2}, @P1)";
其中@P1 = "'\"Spotty\" AND \"Cat\"'"