За последние 24 часа нас посетили 51646 программистов и 1760 роботов. Сейчас ищут 870 программистов ...

mysqli экранирование....

Тема в разделе "PHP для новичков", создана пользователем pinokio, 9 дек 2017.

  1. pinokio

    pinokio Новичок

    С нами с:
    25 июл 2016
    Сообщения:
    160
    Симпатии:
    6
    А я и не знал... Правда там на mysql пример.
    https://habrahabr.ru/post/142599/
    --- Добавлено ---
    вообще у mysqli экранирование странно работает.
    --- Добавлено ---
    А вот она где собачка зарыта... Из доки:
    Код (Text):
    1. Набор символов должен быть задан либо на стороне сервера, либо с помощью API функции mysqli_set_charset(). В противном случае mysqli_real_escape_string() работать не будет.
    --- Добавлено ---
    Капец mysqli... Реально бесполезное экранирование пришлось писать аж вот так
    PHP:
    1. foreach ($array As $key => $value) {
    2.     $stringIns[] = "`".$this->dbConnect->real_escape_string($key)."`";
    3.     $stringValues[] = "'".$this->dbConnect->real_escape_string($value)."'";
    4. }
     
  2. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    некоторые люди всегда найдут способ ошибиться.

    здесь трудности перевода
    "set A to affect B"
    почему-то перевели как
    "сделайте А, иначе B работать не будет"
    что кагбэ искажает изначальный смысл. имелось в виду, что данная настройка влияет на указанную функцию. но поздняк, данный вариант перевода расползся по рунету.

    фактически соединению всегда сопоставлен какой-то набор символов, как правило, если ничего не укажешь на клиенте, то будет использован latin1 (он же cp1250).

    известно, что в старых версиях MySQL был баг для некоторых азиатских мультибайтных кодировок — бала возможна атака с имитацией апострофа внутри "длинного" символа.
    https://stackoverflow.com/a/12118602/272885
    --- Добавлено ---
    указывать кодировку соединения надо, чтобы данные в базе были верными. в этом смысл функции.
     
    denis01 нравится это.
  3. pinokio

    pinokio Новичок

    С нами с:
    25 июл 2016
    Сообщения:
    160
    Симпатии:
    6
    на пдо у меня выглядит это вот так:
    PHP:
    1. static::$db = new \PDO("mysql:host=".$db['host'].";port=".$db['port'].";dbname=".$db['dbname'].";charset=".$db['charset'],
    2.                 $db['username'], $db['password']);
    У меня при создании подключение устанавливается кодировка в пдо, а в mysqli пришлось сделать вот так,
    PHP:
    1. $this->dbConnect = DB::connect();
    2.         $this->dbConnect->set_charset("utf8");
    --- Добавлено ---
    но суть темы вот в этом
    --- Добавлено ---
    но один фиг вот эта хрень:
    Код (Text):
    1. ->real_escape_string($value)
    работает не так как quote у pdo
    --- Добавлено ---
    она не добавляет '' ковыки в начале и конце строки
    --- Добавлено ---
    я скок прогаю на пыхе всё время юзаю pdo никогда не отдавал предпочтений mysqli...
    --- Добавлено ---
    и вообще не трогал его никогда оббегал стороной за 300 км... А тут пришлось Эх... А он работает не так, методы другие ещё и не так работают, эх, пришлось доку штудировать...
     
  4. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Буратина, почему "бесполезное"?! Если нет ни экранирования, ни плейсхолдеров, то возможна инъекция. Так что полезное.

    Было бы удобнее апострофы оставить в теле запроса, а не в переменной. Пример из руководства по функции
    PHP:
    1. $city = "'s Hertogenbosch";
    2.  
    3. $city = $mysqli->real_escape_string($city);
    4.  
    5. /* this query with escaped $city will work */
    6. if ($mysqli->query("INSERT into myCity (Name) VALUES ('$city')")) {
    7.  printf("%d Row inserted.\n", $mysqli->affected_rows);
    8. }
     
  5. pinokio

    pinokio Новичок

    С нами с:
    25 июл 2016
    Сообщения:
    160
    Симпатии:
    6
    Потому что:
    PDO::quote - Мне больше по душе. Логика такова апострофы раставляет сама (помимо экранирования). Значит метод quote полезный а тот бесполезный. Но сори там такого нет. Поэтому получите распишитесь.
    --- Добавлено ---
    Так между прочем классный мультик.
    --- Добавлено ---
    Любил его в детстве
     
  6. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    P.S. в pdo::quote нет нужды, т.к. в pdo нормальные плейсхолдеры есть и с ними всё чётко отрабатывает без добавления апострофов!

    из доки:
    PHP:
    1. $sql = 'SELECT name, colour, calories
    2. FROM fruit
    3. WHERE calories < :calories AND colour = :colour';
    4. $sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
    5. $sth->execute(array(':calories' => 150, ':colour' => 'red'));
    6. $red = $sth->fetchAll();
    7. $sth->execute(array(':calories' => 175, ':colour' => 'yellow'));
    8. $yellow = $sth->fetchAll();
     
  7. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    @artoodetoo, так в mysqli тоже же плейсхолдерить можно, правда, кода чуть больше получается
     
  8. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    там неудобно реализовано
     
  9. pinokio

    pinokio Новичок

    С нами с:
    25 июл 2016
    Сообщения:
    160
    Симпатии:
    6
    Зачем переместили тему я не чего не спрашивал.
    --- Добавлено ---
    Просто зачем?
    --- Добавлено ---
    Я вообще не понимаю зачем ты это пишешь потому что я это прекрасно и без тебя в документации прочёл.
    --- Добавлено ---
     
  10. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    1. Mysqli supports prepared statements with "?" placeholders for parameters. PDO supports both "?" placeholders and also named placeholders, like ":columnName".
    2. Mysqli requires that you use a function to bind each parameter value to the prepared statement. PDO also allows you to simply pass an array of parameter values as you execute the prepared statement.
    я помню как-то пытался, но bind_result убил мои надежды :( выглядело так, что кто-то специально придумал эту "фишку" чтобы заставить программистов страдать.
    --- Добавлено ---
    @pinokio А кто сказал, что без вопроса туда нельзя? Успокойся уже. За тебя решают другие.
     
  11. pinokio

    pinokio Новичок

    С нами с:
    25 июл 2016
    Сообщения:
    160
    Симпатии:
    6
    да ты что? А вот это:
    PHP:
    1. public function where($where) {
    2.         $stringIns = [];
    3.         foreach ($where As $key => $value) {
    4.             $stringIns[] = sprintf('%s=%s', $key, $this->dbConnect->quote($value));
    5.         }
    6.         $this->where = implode(' AND ', $stringIns);
    7.         $this->where = trim($this->where, ' AND ');
    8.         return $this;
    9.     }
    --- Добавлено ---
    И как бы писать bind param как то не особо хочется через quote как то более простая реализация
    --- Добавлено ---
    не спорю при написании конкретного запроса чёткая вещь.
     
  12. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    и что это должно доказывать? я бы написал иначе. sprintf там тоже не нужен )))
     
  13. pinokio

    pinokio Новичок

    С нами с:
    25 июл 2016
    Сообщения:
    160
    Симпатии:
    6
    А то что реализация в три строчки кода.
    --- Добавлено ---
    Чтобы получить массив который передаётся в execute
    Надо сделать следующее:

    PHP:
    1.          
    2. $arr = [];
    3.         foreach ($where As $key => $value) {
    4.             $arr[':'.$key] = $value;
    5.         }
    6.         $sth->execute(array(':calories' => 150, ':colour' => 'red'));  
    Тут как бы тоже три строчки, но
    мне не нравится вот этот костыль
    Код (Text):
    1. $arr[':'.$key]
    Код (Text):
    1. ':'.
    --- Добавлено ---
    Выглядит страшно.
     
  14. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    я уже где-то на форуме писал недавно, что построитель запросов (от Laravel) идеально подходит построения запросов. :D внезапно™

    ни одной подстановки переменной прямо в тело запроса не понадобится. потому что там вообще SQL запрос не торчит наружу. а раз нет текста запроса, то и некуда и незачем подставлять эти экранированные переменные. с этим не накосячить.
     
    mkramer нравится это.
  15. pinokio

    pinokio Новичок

    С нами с:
    25 июл 2016
    Сообщения:
    160
    Симпатии:
    6
    конкатенация в ключе массива.. Не хочу. Не буду. Не заставляйте меня это делать. ))
    --- Добавлено ---
    Это как ?
     
  16. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    я пересказывать доки ларавель не буду. to google "laravel query builder"

    код твой просто кошмар. смех и грех.
     
  17. pinokio

    pinokio Новичок

    С нами с:
    25 июл 2016
    Сообщения:
    160
    Симпатии:
    6
    почему?
    --- Добавлено ---
    Ау
    --- Добавлено ---
    @artoodetoo ауауау
     
  18. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    вызывать sprintf чтобы добавить один символ между двух строк?
    что должен делать trim(…, ' AND ') после implode(' AND '…) ты видимо не в курсе как работает implode.

    видно что это результат копи-пасты. и этот блин человек тут качает права, в раздел профи лезет, ругает потенциальных заказчиков, грубит модераторам.

    ты неадекват, Лёня. нестыдно чего-то не знать. стыдно выдавать себя за крутого чтобы очевидно потом обосраться. и говорить "нет я не обосрался, это не говно". другого и быть не могло.
     
    voral нравится это.
  19. pinokio

    pinokio Новичок

    С нами с:
    25 июл 2016
    Сообщения:
    160
    Симпатии:
    6
    Хорошо возьми этот вставь себе и добавь туда массив такого хар-ра [''] и отправь его туда предварительно убери Трим
    --- Добавлено ---
    Вставь метод*
    --- Добавлено ---
    Не добавь а передай так правильнее сказать
     
  20. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    :D смешно, да. давай ты вставишь себе и уберёшь. это был бесплатный урок.

    а пока я оцениваю твоё упорство в 1 штрафной балл.
     
  21. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

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

    Бред. И не unix-way.
    --- Добавлено ---
    PANIC! ALARM! ALERT! WARNING! А МУЖИКИ-ТО И НЕ ЗНАЮТ!
    Статья от 2012 года.
    Сейчас 2017. И запрос падает с ошибкой, если в нем есть строковое значение, не обрамленное в кавычки.
    Потому как такое значение по умолчанию расценивается как имя столбца/алиаса/переменной/чего-нибудь, но, так как оно отсутствует в скоупе запроса, запрос падает.
    --- Добавлено ---
    Поправьте, если ошибаюсь.
     
    voral нравится это.
  22. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    да всё верно. собственно та статья на хабре о том, что пользовательскому вводу не надо верить + что неправильное использование функций порождает уязвимости, а не о том, что экранирование буквально "бесполезно". )))
     
  23. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    зачем эскейпить если плейсхолдеры есть..
     
  24. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    я сегодня как раз с этим столкнулся.. . решил написать обертку... еще не доделал.. но теперь работа с mysqli и плейсхолдерами выглядит так
    Код (Text):
    1.  
    2.     public function getByIds(array $ids) {
    3.  
    4.         $result = $this->dbQuery(
    5.             'SELECT * FROM {db_prefix}site
    6.             WHERE data1int IN({array_int:ids})
    7.             AND data1int = {int:id}', array(
    8.             'ids' => [1,2,3,4,5,6,7,8,9],
    9.             'id' => 2342,
    10.         ));
    11.  
    12.         $items = [];
    13.         if ($this->dbNumRows($result) > 0) {
    14.             while ($row = $this->dbFetchAssoc($result)) {
    15.                 $items[] = $row;
    16.             }
    17.         }
    18.         $this->dbFreeResult($result);
    19.  
    20.         return $items;
    21.     }
    это пример)) но задумка такая)) еще обертку не полностью доделал..