Предоставление имен таблиц и полей в URL-адресе запроса
мне было поручено создать этот компонент Joomla (да, joomla; но он не связан), и профессор сказал мне, что я должен сделать свой код как можно более динамичным (код, который требует меньшего обслуживания) и избежать жесткого кодирования. Подход, который мы изначально думали, - это взять параметры url, превратить их в объекты и передать их в запрос.
допустим, мы хотим прочитать отель с id # 1 в таблице "отели". допустим в таблице есть поля "hotel_id", "hotel_name" и некоторые другие поля.
теперь подход, который мы приняли при создании строки запроса sql, заключается в анализе запроса url, который выглядел так:
index.php?task=view&table=hotels&hotel_id=1¶m1=something¶m2=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-адресе запроса. Я знаю, что это создает угрозу безопасности, подвергая элементы, которые должны быть видны только на стороне сервера. Текущее решение, о котором я думаю, дает псевдонимы каждой таблице и полю для клиентской стороны, но это будет жесткое кодирование, что противоречит его политике. и кроме того, если бы я сделал это и имел тысячу таблиц для псевдонима, это не было бы практическое.
каков правильный метод для этого без:
- жесткого кодирования вещи
- держите код как динамический и адаптируемый
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 ответов
у меня нет проблем с использованием одних и тех же (или очень похожих) имен в URL и базе данных - конечно, вы можете "разоблачать" детали реализации, но если вы выбираете радикально разные имена в URL и БД, вы, вероятно, выбираете плохие имена. Я также поклонник последовательного именования-общение с кодерами/тестерами / клиентами становится намного сложнее, если все называют все немного иначе.
что меня беспокоит, так это то, что вы позволяете пользователю работать произвольные запросы к базе данных. http://.../index.php?table=users&user_id=1
, сказать? Или http://.../index.php?table=users&password=password
(Не то, что вы должны хранить пароли в открытом виде)? Или http://.../index.php?table=users&age=11
?
если пользователь, подключенный к БД, имеет те же разрешения, что и пользователь, сидящий перед веб-браузером, это может иметь смысл. Как правило, это не так, поэтому вам понадобится какой-то слой, который знает, что такое пользователь, и не может видеть, и этот слой намного проще правильно написать белым списком.
(Если вы вставил достаточно логики в хранимые процедуры, тогда это может сработать, но тогда ваши хранимые процедуры будут имена столбцов жесткого кода...)
при составлении SQL-запроса с данными из входных данных он представляет угрозу безопасности. Но имейте в виду, что значения столбцов вставляются в поля, принимая входные данные от пользователя, анализируя его и составляя с ним SQL-запрос (за исключением подготовленных операторов). Поэтому, когда все сделано правильно, вам не о чем беспокоиться - просто ограничьте пользователя этими столбцами и таблицами. Код/база данных программного обеспечения с открытым исходным кодом видны всем - и это не вредит системе так сильно, как было бы думать.
ваш aliasses может быть rot13()
на мета / имя ваших объектов.
хотя, если вы избегаете ввода соответственно при работе с этими именами, я не вижу никаких проблем в раскрытии их имен.