Озабоченность по поводу полнотекстового поиска SQL Server 2008 - PullRequest
11 голосов
/ 31 августа 2009

Я построил запрос T-SQL так:

DECLARE @search nvarchar(1000) = 'FORMSOF(INFLECTIONAL,hills) AND FORMSOF(INFLECTIONAL,print) AND FORMSOF(INFLECTIONAL,emergency)'

SELECT * FROM Tickets
WHERE ID IN (
                -- unioned subqueries using CONTAINSTABLE
                            ...
            )

Графическим интерфейсом для этого поиска будет страница aspx с одним текстовым полем, в котором пользователь может выполнять поиск.

Я планирую как-то сконструировать поисковый запрос, как в примере выше (@search).

У меня есть некоторые опасения:

  • Является ли приведенный в качестве примера поисковый запрос выше или единственный способ включить перегибы всех слов в поиске?
  • Должен ли я отделить слова и составить поисковый термин в C # или T-SQL. Я склоняюсь к C # для принятия решений / зацикливания / построения, но мне нужно ваше мнение.
  • Я ненавижу динамическое построение SQL из-за риска внедрения. Как я могу защититься от этого?
  • Должен ли я вместо этого использовать FREETEXTTABLE? Есть ли способ заставить FREETEXT искать ВСЕ слова вместо ЛЮБОГО?
  • В общем, как еще вы могли бы это сделать?

Ответы [ 4 ]

3 голосов
/ 07 сентября 2009

Я недавно использовал полнотекстовый поиск, поэтому постараюсь ответить на некоторые ваши вопросы.

• «Я ненавижу строить sql динамически из-за риска инъекции. Как я могу защититься от этого?»

Я использовал метод очистки, как этот:

static string SanitizeInput(string searchPhrase)
    {
        if (searchPhrase.Length > 200)
            searchPhrase = searchPhrase.Substring(0, 200);

        searchPhrase = searchPhrase.Replace(";", " ");
        searchPhrase = searchPhrase.Replace("'", " ");
        searchPhrase = searchPhrase.Replace("--", " ");
        searchPhrase = searchPhrase.Replace("/*", " ");
        searchPhrase = searchPhrase.Replace("*/", " ");
        searchPhrase = searchPhrase.Replace("xp_", " ");

        return searchPhrase;
    }

• Должен ли я вместо этого использовать FREETEXTTABLE? Есть ли способ заставить FREETEXT искать ВСЕ слова вместо ЛЮБОГО?

Я использовал FREETEXTTABLE, но мне нужно было любое из слов. Столько, сколько я прочитал об этом (и я прочитал довольно много), вы должны использовать CONTAINSTABLE для поиска ВСЕХ слов или различных комбинаций. FREETEXTTABLE кажется более легким решением, но не тем, которое нужно выбирать, когда вам нужны более глубокие настройки.

2 голосов
/ 14 сентября 2009

Дэн, мне нравится твой метод SanitizeInput. Я переработал его, чтобы сделать его более компактным и немного повысить производительность.

 static string SanitizeInput(string searchPhrase, int maxLength)
        {
            Regex r = new Regex(@";|'|--|xp_|/\*|\*/", RegexOptions.Compiled);
            return r.Replace(searchPhrase.Substring(0, searchPhrase.Length > maxLength ? maxLength : searchPhrase.Length), " ");
        }

        static string SanitizeInput(string searchPhrase)
        {
            const int MAX_SEARCH_PHRASE_LENGTH = 200;
            return SanitizeInput(searchPhrase, MAX_SEARCH_PHRASE_LENGTH);
        }

Я согласен, что FreeTextTable слишком легок для решения.

0 голосов
/ 15 сентября 2009

Все наши поиски по столбцам в базе данных, которые имеют предопределенные допустимые символы. Наш алгоритм поиска включает это с регулярным выражением, которое позволяет только эти предопределенные символы. Из-за этого экранирование в строке поиска не требуется. Наше регулярное выражение отсеивает любые попытки внедрения в веб-код (asp & aspx). Для стандартных комментариев пользователей мы используем экранирование, при котором изменяются все символы, которые могут быть использованы для нанесения вреда в SQL, ASP, ASPX и Javascript.
Сайт TransStar http://latranstar.tann.com/ использует расширенную форму Soundex для поиска названий улиц, адресов и городов в любой точке Южной Калифорнии. Сам по себе Soundex устраняет необходимость в коде для предотвращения инъекций, поскольку он работает только с буквенными символами.

0 голосов
/ 10 сентября 2009

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

Я бы порекомендовал построить поисковый термин в C #;Передача окончательного поискового термина в качестве параметра, подобного уже упомянутому.

Насколько я помню, FREETEXTTABLE использует средства разбиения по словам для полного разложения поисковых терминов на отдельные компоненты. Однако оператор FREETEXTTABLE автоматически разбивает слова на инфлективные эквиваленты , поэтому вам не придется создавать сложный оператор CONTAINSTABLE, если вы решите его использовать.

Вы можетеINNER JOIN результаты нескольких FREETEXTTABLE запросов для получения эквивалентного AND результата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...