#sql #sql-server #stored-procedures #dynamic #escaping
#sql #sql-сервер #хранимые процедуры #динамический #экранирование
Вопрос:
У меня есть динамическая процедура, в которой я хочу использовать приведенное ниже как часть моего предложения Where (все остальное работает по назначению).
В настоящее время это создает следующую ошибку: Incorrect syntax near the keyword 'LIKE'
AND CASE WHEN ' @searchCategory ' <> ''dateRec'' THEN
(R.' @searchCategory ' LIKE ''%' @searchTerm '%'')
ELSE
(R.dateRec = ' CONVERT(VARCHAR, @searchTerm, 111) ')
END
Как здесь будет выглядеть правильное экранирование?
Комментарии:
1. Пожалуйста, отправьте весь запрос целиком, вы удалили кавычки, и динамический sql инвертируется на нединамический.
2. Остальная часть процедуры работает и слишком длинная, чтобы публиковать ее здесь — речь идет только об этих строках.
3. ХОРОШО, все в порядке, это недопустимо
CASE WHEN xxx <> 'dateRec' THEN (R.xxx LIKE '%yyy%')
оператор THEN сообщает SQL, что использовать, и вы выполняете другое сравнение. Это не проблема, это проблема синтаксиса.4. Хорошо, это возможно. У меня нет большого опыта работы с динамическими процедурами. Как бы мне написать это правильно?
5. Что именно вы пытаетесь сделать?
Ответ №1:
Я считаю, что это то, что вы ищете:
declare @sql nvarchar(max), @searchCategory nvarchar(max), @searchTerm nvarchar(max)
set @searchCategory = 'dateRec'
set @searchTerm = 'yyy'
set @sql =
'AND (
(''' @searchCategory ''' <> ''dateRec'' AND (R.' @searchCategory ' LIKE ''%' @searchTerm '%''))
OR
(''' @searchCategory ''' = ''dateRec'' AND (R.dateRec = ''' CONVERT(VARCHAR, @searchTerm, 111) '''))
)'
print @sql
Комментарии:
1. Это здорово — большое спасибо! Что в итоге делает печать? В настоящее время я завершаю свою процедуру с помощью EXEC(@sql).
2. Это встраивает текст
@searchTerm
в произвольной форме в SQL. Это открывает вам путь к атаке с использованием SQL-инъекций LittleBobbyTables. Вместо использованияEXEC
этого shoudl используйтеsp_executesql
и, таким образом, сможете передавать параметры в dynamic-sql. Таким образом@searchCategory
, требуется только подстановка в sql-строку, и это можно проверить в белом списке, чтобы убедиться, что это не атака.3. @MatBailie: Спасибо за это !
Ответ №2:
Предполагая, что содержимое @searchCategory фактически не содержит символов '
…
SET @sql = 'AND '
CASE WHEN @searchCategory <> 'dateRec' THEN
'(R.' @searchCategory ' LIKE ''%'' @searchTerm ''%'')'
ELSE
'(R.dateRec = CONVERT(VARCHAR, @searchTerm, 111))'
END
Это даст либо….
AND (R.foobar LIKE '%' @searchTerm '%')
или…
AND (R.dateRec = CONVERT(VARCHAR, @searchTerm, 111))
Это означает, что вы все равно будете передавать @searchTerm
в sp_executesql
качестве параметра, чтобы защитить вас от атак SQL-инъекций.
Вы НЕ хотите напрямую вставлять текст произвольной формы пользователя в свой SQL. Текст в произвольной форме должен оставаться в качестве параметра, чтобы закрыть эту дыру в безопасности.
(Я также предполагаю, что у вас есть белый список допустимых значений @searchCategory
, чтобы предотвратить злоупотребление этим с помощью SQL-инъекционной атаки?.)
Редактировать :
Пример динамического sql, который поддерживает параметризацию….
DECLARE @SQL nvarchar(500);
SET @SQLString = N'SELECT * FROM table WHERE ' @param1 ' = @param;';
EXECUTE sp_executesql
@SQL,
'@param NVARCHAR(500)',
@param2
Используя этот метод, вам нужно проверить, что @param1 действительно является допустимым именем поля, например, используя белый список, но вам не нужно проверять @param2. Это связано с тем, что @param2 передается sp_executesql
как сам параметр. Это похоже на динамическое создание хранимой процедуры с параметрами, а не на встраивание всех ваших значений в строку sql, что делает вас открытыми для серьезных атак sql-инъекций.
Редактировать :
Это не тот случай, когда оператор встраивается в LIKE
CASE
оператор. Что здесь делается, так это создание строки, которая создает строковый литерал LIKE
, с помощью оператора CASE .
Это почти то же самое, что и это…
SET @sql = 'AND '
CASE WHEN @searchCategory <> 'dateRec' THEN
'A string with the word' ' LIKE ' 'in it'
ELSE
'A different string without that word in it'
END
Комментарии:
1. @JiggsJedi — Это не то, что вы думаете. это
LIKE
просто фрагмент текста (строковый литерал), а не команда. Это оператор case создает строку SQL, где строка SQL содержит текстLIKE
. Это не оператор case с оператором LIKE внутри него.2. @JiggsJedi — я не говорю, что это вообще допустимо. Вы правы, что ваш пример верен. То, что я написал, не соответствует вашему примеру. Я обновлю свой ответ, чтобы сделать его более понятным.
3. @MatBailie: Спасибо за это — это все еще очень полезно!
4. Я отказываюсь от своих комментариев. Клянусь вам, ДЕЛО было в » когда я впервые посмотрел. Вы правы, сэр.