Предоставление имени таблицы и имен полей в URL запроса - PullRequest
6 голосов
/ 24 июля 2011

Мне было поручено создать этот компонент Joomla (да, joomla; но он не связан), и профессор сказал мне, что я должен сделать свой код как можно более динамичным (код, который требует меньшего количества обслуживания) и избегать жесткого кодирования. Первоначально мы подумали, что взяли параметры URL, превратили их в объекты и передали их в запрос.

Допустим, мы хотим прочитать отель с идентификатором № 1 в таблице «отели». Допустим, в таблице есть поля "hotel_id", "hotel_name" и некоторые другие поля.

Теперь, подход, который мы использовали при создании строки запроса sql, состоит в том, чтобы проанализировать URL-запрос, который выглядел так:

index.php?task=view&table=hotels&hotel_id=1&param1=something&param2=somethingelse

и превратил его в объект PHP, подобный этому (показан в JSON-эквиваленте, более понятный):

obj = {
  'table':'hotel',
  'conditions':{
        'hotel_id':'1',
        'param1':'something',
        'param2':'somethingelse'
}

и SQL-запрос будет выглядеть примерно так, когда условия зацикливаются и добавляются в строку, где поле и значение предложения WHERE являются ключом и значением объекта (для простоты все еще в форме JSON):

SELECT * FROM obj.table WHERE hotel_id=1 AND param1=something and so on...

Проблема, которая меня беспокоила, заключалась в том, что в URL-адресе запроса отображалось имя таблицы и имена полей. Я знаю, что это создает угрозу безопасности, выставляя элементы, которые должны быть видны только на стороне сервера. Текущее решение, о котором я думаю, - дать псевдонимы каждой таблице и полю для клиентской стороны, но это было бы жестким кодированием, что противоречит его политике. и кроме того, если бы я сделал это и имел бы тысячи таблиц с псевдонимами, это было бы непрактично.

Какой правильный способ сделать это без:

  1. Жесткий код
  2. сохранить код как динамический и адаптируемый

EDIT:

Что касается произвольных запросов (я забыл включить это), то, что в настоящее время останавливает их в серверной части, - это функция, которая берет ссылку из жестко закодированного объекта (более похожего на файл конфигурации, показанный здесь), и анализирует URL, выбирая параметры или сопоставляя их.

Конфиг выглядит так:

// 'hotels' here is the table name. instead of parsing the url for a table name
// php will just find the table from this config. if no match, return error.
// reduces risk of arbitrary tables.

'hotels' => array(      

  // fields and their types, used to identify what filter to use

  'structure' => array(  
    'hotel_id'=>'int',
    'name'=>'string',
    'description'=>'string',
    'featured'=>'boolean',
    'published'=>'boolean'
  ),

   //these are the list of 'tasks' and accepted parameters, based on the ones above
   //these are the actual parameter names which i said were the same as field names
   //the ones in 'values' are usually values for inserting and updating
   //the ones in 'conditions' are the ones used in the WHERE part of the query

  'operations' =>array(  
    'add' => array(
      'values' => array('name','description','featured'),
      'conditions' => array()
    ),
    'view' => array(
    'values' => array(),
    'conditions' => array('hotel_id')
    ),
    'edit' => array(
    'values' => array('name','description','featured'),
    'conditions' => array('hotel_id')
    ),
    'remove' => array(
    'values' => array(),
    'conditions' => array('hotel_id')
    )
  )
)

и так, из этого списка конфигурации:

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

Я на самом деле сделал это после того, как увидел компонент в Joomla, который использует эту стратегию. Это сокращает модель и контроллер до 4 динамических функций, которые будут CRUD, оставляя только файл конфигурации, который будет единственным редактируемым файлом позже (это было то, что я имел в виду в динамическом коде, я только добавляю таблицы и задачи, если требуются дополнительные таблицы) но я боюсь, что это может создать угрозу безопасности, о которой я, возможно, еще не знал.

Есть идеи для альтернативы?

Ответы [ 3 ]

1 голос
/ 24 июля 2011

При составлении SQL-запроса с данными из входных данных это представляет угрозу безопасности.Но имейте в виду, что значения столбцов вставляются в поля, принимая данные от пользователя, анализируя их и составляя с ними SQL-запрос (за исключением подготовленных операторов).Поэтому, если все сделано правильно, вам не о чем беспокоиться - просто ограничьте пользователя этими столбцами и таблицами.Код / база данных программного обеспечения с открытым исходным кодом видны всем - и это не вредит системе так сильно, как можно было бы подумать.

1 голос
/ 25 июля 2011

У меня нет проблем с использованием одинаковых (или очень похожих) имен в URL и базе данных & mdash; Конечно, вы можете «разоблачать» детали реализации, но если вы выбираете радикально разные имена в URL и БД, вы, вероятно, выбираете плохие имена. Я также являюсь поклонником последовательных имен & mdash; общение с программистами / тестировщиками / клиентами становится намного сложнее, если все называют что-то немного другое.

Что меня беспокоит, так это то, что вы позволяете пользователю выполнять произвольные запросы к вашей базе данных. http://.../index.php?table=users&user_id=1, говорите? Или http://.../index.php?table=users&password=password (не то, что вы должны хранить пароли в открытом тексте)? Или http://.../index.php?table=users&age=11?

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

(Если вы внедрили достаточное количество логики в хранимые процедуры, то это может сработать, но тогда ваши хранимые процедуры будут жестко кодировать имена столбцов ...)

0 голосов
/ 24 июля 2011

Ваш псевдоним может быть rot13() на мета / имени ваших объектов.

Хотя, если вы избегаете ввода соответствующим образом при работе с этими именами, я не вижу проблем в раскрытии их имен.

...