Динамический SQL - поисковый запрос - переменное количество ключевых слов - PullRequest
4 голосов
/ 01 октября 2008

Мы пытаемся обновить наш классический поисковый движок asp, чтобы защитить его от внедрения SQL. У нас есть функция VB 6, которая динамически формирует запрос, объединяя запрос на основе различных параметров поиска. Мы преобразовали это в хранимую процедуру, используя динамический sql для всех параметров, кроме ключевых слов.

Проблема с ключевыми словами состоит в том, что пользователь вводит слова с переменным числом, и мы хотим искать в нескольких столбцах каждое ключевое слово. Поскольку мы не можем создать отдельный параметр для каждого ключевого слова, как мы можем создать безопасный запрос?

Пример:

@CustomerId AS INT
@Keywords AS NVARCHAR(MAX)

@sql = 'SELECT event_name FROM calendar WHERE customer_id = @CustomerId '

--(loop through each keyword passed in and concatenate)

@sql = @sql + 'AND (event_name LIKE ''%' + @Keywords + '%'' OR event_details LIKE ''%' + @Keywords + '%'')'

EXEC sp_executesql @sql N'@CustomerId INT, @CustomerId = @CustomerId

Каков наилучший способ справиться с этим и обеспечить защиту от внедрения SQL?

Ответы [ 4 ]

3 голосов
/ 01 октября 2008

Возможно, вам не понравится это слышать, но, возможно, вам лучше вернуться к динамическому построению вашего SQL-запроса в коде перед его выдачей в базу данных. Если вы используете заполнители параметров в строке SQL, вы получаете защиту от атак внедрения SQL.

Пример:

string sql  = "SELECT Name, Title FROM Staff WHERE UserName=@UserId";
using (SqlCommand cmd = new SqlCommand(sql))
{
  cmd.Parameters.Add("@UserId", SqlType.VarChar).Value = "smithj";

Вы можете построить строку SQL в зависимости от набора столбцов, которые необходимо запросить, а затем добавить значения параметров после завершения строки. Это немного трудновато, но я думаю, что это намного проще, чем иметь действительно сложный TSQL, который выбирает множество возможных комбинаций возможных входных данных.

1 голос
/ 01 октября 2008

У вас есть 3 варианта здесь.

  1. Используйте функцию , которая преобразует таблицы списков и присоединяется к ней. Так что у вас будет что-то вроде этого.

    SELECT * 
    FROM calendar c
       JOIN dbo.fnListToTable(@Keywords) k 
           ON c.keyword = k.keyword  
    
  2. Иметь фиксированный набор параметров и разрешать поиск по максимуму из N ключевых слов в

    CREATE PROC spTest
    @Keyword1 varchar(100),
    @Keyword2 varchar(100),
    .... 
    
  3. Напишите функцию экранирования строк в TSQL и экранируйте ваши ключевые слова.

0 голосов
/ 18 октября 2010

Вы можете попробовать это:

SELECT * FROM [tablename] WHERE LIKE % +keyword%
0 голосов
/ 01 октября 2008
  • Если вам это не нужно, вы можете просто удалить любой символ, которого нет в [a-zA-Z] - большинство из этих вещей не будут в поисках, и вы не должны быть в состоянии впрыснуть таким образом и вам не нужно беспокоиться о ключевых словах или о чем-либо подобном. Однако, если вы разрешаете цитаты, вам нужно быть более осторожным.

  • Как и в sambo99 # 1, вы можете вставить ключевые слова во временную таблицу или табличную переменную и присоединиться к ней (даже с использованием подстановочных знаков) без опасности внедрения:

Это не совсем динамично:

SELECT DISTINCT event_name
FROM calendar
INNER JOIN #keywords
    ON event_name LIKE '%' + #keywords.keyword + '%'
    OR event_description LIKE '%' + #keywords.keyword + '%'
  • На самом деле вы можете сгенерировать SP с большим количеством параметров вместо того, чтобы кодировать его вручную (установите значения по умолчанию '' или NULL в зависимости от ваших предпочтений при кодировании поисковых запросов). Если вы обнаружили, что вам нужно больше параметров, было бы просто увеличить количество сгенерированных параметров.

  • Вы можете переместить поиск в полнотекстовый индекс вне базы данных, такой как Lucene, а затем использовать результаты Lucene для извлечения соответствующих строк базы данных.

...