Параметризованные столбцы SQL? - PullRequest
8 голосов
/ 20 сентября 2008

У меня есть некоторый код, который использует параметризованные запросы для предотвращения внедрения, но мне также нужно иметь возможность динамически создавать запрос независимо от структуры таблицы. Как правильно это сделать?

Вот пример, скажем, у меня есть таблица с столбцами Имя, Адрес, Телефон. У меня есть веб-страница, на которой я запускаю Показать столбцы и заполняю их выпадающим меню в качестве параметров.

Далее у меня есть текстовое поле с именем Поиск . Это текстовое поле используется в качестве параметра.

В настоящее время мой код выглядит примерно так:

result = pquery('SELECT * FROM contacts WHERE `' + escape(column) + '`=?', search);

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

Как я могу убедиться, что это работает так, как я намереваюсь?

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

Ответы [ 6 ]

6 голосов
/ 20 сентября 2008

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

@columns = qw/Name Address Telephone/;
if ($columns[$param]) {
  $query = "select * from contacts where $columns[$param] = ?";
} else {
  die "Invalid column!";
}

run_sql($query, $search);
0 голосов
/ 20 сентября 2008

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

if ( $column !~ /^\w+$/ ) {
  die "Bad column name [$column]";
}
0 голосов
/ 20 сентября 2008

В стандартном SQL идентификаторы с разделителями заключаются в двойные кавычки. Это означает, что:

SELECT * FROM "SomeTable" WHERE "SomeColumn" = ?

выберет таблицу с именем SomeTable с показанной заглавной буквой (а не преобразованную в регистр версию имени) и применит условие к столбцу с именем SomeColumn с показанной заглавной буквы.

Само по себе это не очень полезно, но ... если вы можете применить технику escape () с двойными кавычками к именам, введенным через веб-форму, то вы можете достаточно уверенно составить запрос.

Конечно, вы сказали, что хотите избежать использования escape - и вам действительно не нужно использовать его для параметров, которые вы предоставляете? местоблюститель. Но если вы вводите в запрос предоставленные пользователем данные, вам необходимо защитить себя от злоумышленников.

Разные СУБД имеют разные способы предоставления идентификаторов с разделителями. Например, в MS SQL Server вместо двойных кавычек используются квадратные скобки [SomeTable].

0 голосов
/ 20 сентября 2008

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

0 голосов
/ 20 сентября 2008

Я использую ADO.NET и команды SQL и SQLParameters для тех команд, которые решают проблему Escape. Так что, если вы также находитесь в среде инструментов Microsoft, я могу сказать, что я очень успешно использую это для построения динамического SQL и в то же время для защиты своих параметров

удачи

0 голосов
/ 20 сентября 2008

Хитрость заключается в том, чтобы быть уверенным в ваших побегах и проверке рутин. Я использую свою собственную escape-функцию SQL, которая перегружена для литералов разных типов. Нигде я не вставляю выражения (в отличие от литеральных значений в кавычках) непосредственно из пользовательского ввода.

Тем не менее, это может быть сделано, я рекомендую отдельную - и строгую - функцию для проверки имени столбца. Разрешить принимать только один идентификатор, например,

/^\w[\w\d_]*$/

Вам придется полагаться на предположения, которые вы можете сделать относительно имен собственных столбцов.

...