Показать сообщение отдельно
  #14 (permalink)  
Старый 30.01.2018, 07:45
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

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

Ваш запрос не делает элементарного, экранирование данных. Но если это и будет сделано, то это будет означать только одно - текущий запрос исключает sql-инъекцию. Но данные помещенные в базу могут служить источником данных вложенных запросов впоследствии, а значит нужно будет всегда помнить об этом и производить их экранирование. Все потому, что вы данные не фильтруете, вас вообще не интересует действительно ли это ваши данные, соответствуют ли они типам ожидаемым.

Контекст вашей темы, это оптимизация. А что такое по вашему оптимизация - красиво выполнить действия на клиенте? А на сервере как получится?

Если СУБД не позволяет записать в базу набор данных в рамках одного запроса, это плохо, но придется выполнять массу запросов. Но если позволяет, то почему же вы не думаете об оптимизации? Я ведь показывал что нужно сделать, да даже если бы и не показал, вы, думая об оптимизации, просто обязаны изучить возможности СУБД, дабы сделать запись оптимальной.

Это вы обязаны знать - http://fi2.php.net/manual/ru/security.database.php.
Это очень желательно знать - http://fi2.php.net/manual/ru/book.filter.php.
Это http://fi2.php.net/manual/ru/book.mysqli.php или это http://fi2.php.net/manual/ru/book.pdo.php нужно использовать вместо этого http://fi2.php.net/manual/ru/book.mysql.php.

Используя оригинальное расширение MySQL, вы обязаны сами экранировать данные подставляемые в запрос функцией mysql_real_escape_string(). При этом ожидаемые данные типа integer можно приводить к данному типу, и при этом помещать их в кавычки совсем не требуется.

Допустим, если в ключах knb и inb ожидаем integer, а в cdt строку, то данные первых двух ключей приводим к integer, а последнего экранируем функцией mysql_real_escape_string() и обрамляем кавычками. Подготовив таким образом данные для запроса, делаем запрос:

if($data = json_decode($_POST['kye'])) {
    //каждое вложение $data при таком декодировании будет объектом
    //подготавливаем запрос
    $sql = 'INSERT INTO FROM table (...) VALUES ' . implode(',', array_map(function($v) {
               return '(' . (int)$v->kbn . ',' . (int)$v->inb . ',"' . mysql_real_escape_string($v->cdt) . '")'; 
    }, $data));
    //выполняем запрос
    mysql_query($sql);    
}


При подготовке запроса можно не просто приводить данные к типу и экранировать, а производить их фильтрацию - если (int)$v->kbn или (int)$v->inb ноль, а это не должно быть, значит липовые данные, завершаем работу. Дату ли содержит $v->cdt или "Привет Федя!" ведь тоже не проблема проверить. То есть, либо if((int)$v->kbn) ..., либо используем класс Filter.

А в mysqli и PDO все, кроме фильтрации в контексте "то ли пришло?", можно возложить на sql-драйвер, указав типы и используя подстановки. Драйвер подготовит запрос корректно экранируя и подставив данные в запрос. Запрос будет выглядеть как

'INSERT INTO FROM table (...) VALUES (?,?,?),(?,?,?),(?,?,?),...'

На исполнение отдается этот запрос и массив данных - все вложенные массивы помещаются в один одномерный. Декодирование JSON при этом должно возвращать массив, указывая функции json_decode вторым параметром true/1.

И почитайте о различиях разбора в РНР строковых значений помещенных в одинарные и двойные кавычки.

Последний раз редактировалось laimas, 30.01.2018 в 07:50.
Ответить с цитированием