За последние 24 часа нас посетили 30849 программистов и 1444 робота. Сейчас ищет 881 программист ...

Pdo::prepare

Тема в разделе "PHP для новичков", создана пользователем askanim, 19 июн 2016.

  1. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    Тут у меня появился вопрос. А чё всё что пападает в prepare например как у меня ниже
    PHP:
    1. $result= $db->prepare($this->Update . $this->tableName . ' SET ' . $stringUp . $this->where);
    2. $result->execute();
    автоматически экранируется при добавлении в базу ?
     
  2. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    В твоём виде - нет. А вообще - да.

    Идея в том, что обычный запрос идет в текстовом режиме, а значит надо экранировать сущности, которые влияют на строку. Кавычки, бэкслэши и тп. В подготовленном запросе на сервер сначала отправляется шаблон с позициями переменных, а потом отдельно уже докидываются значения этих переменных. В этом случае передаваемые строки уже не ломают запрос и можно обойтись без экранирования. Как минус - подготовленный запрос выполняется в 1 + N команд, то есть сначала отправляется сам шаблон, а потом N-раз данные для него. Если надо выполнить только один запрос, то этом может создать лишнюю нагрузку по сравнению с текстовым режимом обычных запросов. Но в случае с несколькими запросами с разными данными - дает преимущество, так как не нужно тратить время на очередной разбор текстового запроса.
     
  3. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    Можешь привести пример в котором данные экранируются? Просто я не могу понять как мне правильно построить универсальный запрос который я бы вызывал методом например вот как у меня сейчас.

    PHP:
    1. //Функция добавления данных в таблицу БД
    2.     public function Insert($arr) {
    3.  
    4.         $db = Db::getConnection();
    5.         $stringIns = '';
    6.  
    7.         foreach ($arr as $key => $value) {
    8.             $stringIns = $stringIns.', '.$key.'="'.$value.'"';
    9.         };
    10.         $stringIns = trim($stringIns, ', ');
    11.  
    12.         $result = $db->prepare($this->Insert . $this->tableName . ' SET ' . $stringIns);
    13.         $result->execute();
    14.  
    15.     }
     
  4. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    Показываю на примере всеми любимой Жанны д'Арк

    Итак. Бабу зовут Jeanne d'Arc.
    Есть запрос вида
    PHP:
    1. SELECT '%name%' `name`
    где %name% должно принять нашу Жанну.

    Простой текстовый режим. Не экранируем и сразу подставляем значение переменной в строку:
    PHP:
    1. SELECT 'Jeanne d'Arc' `name`
    то есть ломается запрос

    А вот экранированное значение, подставленное в ту же строку:
    PHP:
    1. SELECT 'Jeanne d\'Arc' `name`
    всем хорошо.

    В процессе разбора сервер выделит из этой строки шаблон запроса и его данные. Условно шаблон будет как показано ранее с процентом, а данные - то как зовут бабу. То есть без экранов всяких.

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

    ты сейчас формируешь текстовый запрос и передаешь его как шаблон подготовленного шаблона. А хочешь делать подготовленный запрос и потом подставлять в него данные.
     
    askanim нравится это.
  5. denis01

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

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
  6. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    @askanim В твоём случае я бы не делал подготовленные запросы, а проэканировал бы всё вручную.

    PHP:
    1. public function Insert($arr) {
    2.  
    3.        $db = Db::getConnection();
    4.        $stringIns = '';
    5.        // Не понятно, что там у тебя в $db, но предположим, что PDO
    6.        $stringIns = []; // Можно и так, как у тебя, но мне больше нравится так
    7.        foreach ($arr as $key => $value) {
    8.            // PDO::quote сама добавляет апострофы
    9.            $stringIns[] = sprintf("%s=%s", $key, $db->quote($value));
    10.        };
    11.        $stringIns = implode(",", $stringIns);
    12.  
    13.        $db->query($this->Insert . $this->tableName . ' SET ' . $stringIns);
    14. }
    А с подготовленными - это тебе надо было в запрос вместо данных расставлять вопросы:
    PHP:
    1. $stringIns=$stringIns.', '.$key.'=?';
    А потом в execute() передать значения
     
    #6 mkramer, 19 июн 2016
    Последнее редактирование: 19 июн 2016
    askanim нравится это.
  7. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    Да я вкурсе в ручную так всегда и делал. Но в моём случае я по циклу забиваю сам запрос автоматически исходя и
    Да именно pdo там и есть
     
  8. denis01

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

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    у тебя есть названия полей, ты должен им присвоить значения, эти названия полей прописаны в скрипте, их изменить нельзя пользователю, он их только может заполнять,
    вот из этих названий полей и делаешь sql шаблон для prepare, потом передаёшь массив где ключи названия этих полей, а значения которые передал пользователь
     
  9. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    это библиотека, я использую DAO Оболочку запросов. Написал вон сам как выше показал, это не для, конечного пользователя а для разработчика. Если бы было для конечного пользователя ясен бы был пень что я сделал не что такое

    PHP:
    1.     $result = $db->prepare(INSERT INTO 'Tablename' SET Value=:Value);
    2.      $result->bindParam(':Value', $_POST['Value']);
    3.      $result->execute();
    4.  
    5.      // И если там не одно значение можно просто в execute передать массив.
    6.     // Вот и всё...
    7.     А я составляю оболочку запроса чтобы можно было сделать так ну у меня так собственно уже и можно
    8.  
    9.    $this->table('tablename')->Insert(['Где ключ массива имя столбца в таблице' => 'А значение ключа, подставляем переменную которую туда будем записывать полученной из пост']);
    10.   //Как то так. Так вот я ума не приложил как prepare перебрать этот массив так чтобы составить такие вот
     
    denis01 нравится это.
  10. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    Затестил pdo->quote($value);

    Всё клёво но есть одно но символы типа Знаков '>' руинят сам php код и тд :)
    Затестил вот такой текст.

    PHP:
    1. %^^&!@$!R%$@#^*U&^(*&)!)@%$*#^%)#_@(_!&($&#$#^)$#)_%&?>BGF:N"GFN<:L<G<RGS>?<ZX<C?"PWFK
     
  11. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    У меян проблема с экранированием спец символов... Я тут сунул с мана вот такую вот функцию, но она удаляет мне просто все теги....
    PHP:
    1. function strip_tags_content($text, $tags = '', $invert = FALSE) {
    2.  
    3.     preg_match_all('/<(.+?)[\s]*\/?[\s]*>/si', trim($tags), $tags);
    4.     $tags = array_unique($tags[1]);
    5.  
    6.     if(is_array($tags) AND count($tags) > 0) {
    7.         if($invert == FALSE) {
    8.             return preg_replace('@<(?!(?:'. implode('|', $tags) .')\b)(\w+)\b.*?>.*?</\1>@si', '', $text);
    9.         }
    10.         else {
    11.             return preg_replace('@<('. implode('|', $tags) .')\b.*?>.*?</\1>@si', '', $text);
    12.         }
    13.     }
    14.     elseif($invert == FALSE) {
    15.         return preg_replace('@<(\w+)\b.*?>.*?</\1>@si', '', $text);
    16.     }
    17.     return $text;
    Мне нужно чтобы как ввели так и получили только чтобы это всё заэкранировалось и не ломало код.... Не могу понять какую функцию из обработки строк заюзать чтобы сделало что мне нужно...
    --- Добавлено ---
    решил проблему с тегами....
    PHP:
    1. $postName = html_entity_decode($_GET['rout']);
    2. echo htmlentities($postName);
    3. // но один хрен вот такая строка ломает мне все просто
    4. //<div>Привет?">:""":":?>?#"%"@#:RT">>?">>:?>"?>"???"%#:%">%#"%,№"Э%№Ж%,Э%</div>
    5. ....
     
  12. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Что за чушь? Коду php по барабану, какие символы внутри строковых переменных (разве что с нулевым символом бывают проблемы, из-за того, что библиотеки написаны на C, а там нулевым символом конец строки отмечается. Но мне не разу не попадалась пока необходимость работы с нулевым символом на php)!

    Если ты про XSS, то там атака идёт не на код php, а на код HTML (чувствую разницу!), типа я ввёл тебе плохой нехороший javascript, и если ты неправильно выводишь данные, то этот код сработал. Поэтому:
    1. При добавлении в базу данных надо проэкранировать символы, которые могут порушить запрос с помощью PDO::quote, или с использованием подготовленых запросов
    2. При выводе данных, которые гарантированно не будут содержать текст html, прогнать их через htmlspecialchars
    3. Если нужно вывести данные, которые должны содержать html, но хочется себя обезопасить, нужно использовать либо стандартную функцию strip_tags, для того чтобы убрать все теги, кроме разрешённых, либо более мощные сторонние средства, к примеру HtmlPurifier (http://htmlpurifier.org/)
    Т.е. в базу мы записываем данные как есть, не портим их. А вот при выводе обрабатываем, чтоб не были возможны XSS-атаки
     
    artoodetoo и askanim нравится это.
  13. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    PHP:
    1. //<div>Привет?">:""":":?>?#"%"@#:RT">>?">>:?>"?>"???"%#:%">%#"%,№"Э%№Ж%,Э%</div>
    2. // У меня это строка не экронируется обрывается на пол пути
    3. // вот здесь
    4. //<div>Привет?">:""":":?>? - и дальше пусто даже скрипт не идёт дальше вообще весь.
     
  14. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Ничего ломать не должно после htmlentities. Этот бред должен быть показан как есть. http://phpfiddle.org/lite/code/7m6e-q5bm
    --- Добавлено ---
    Вот это нафига?
     
  15. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    html_entity_decode — Преобразует все HTML-сущности в соответствующие символы
     
  16. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Я в курсе, если что :cool: Почему ты считаешь, что на вход в $_GET тебе придут сущности?
     
  17. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    PHP:
    1.  echo htmlentities($_GET['rout']);
    Не фига :(
    Вот строка в браузере...
    PHP:
    1. //http://sosed.ru/?rout=%3Cdiv%3E%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82?%22%3E:%22%22%22:%22:?%3E?#"%"@#:RT">>?">>:?>"?>"???"%#:%">%#"%,№"Э%№Ж%,Э%</div>
     
  18. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
  19. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    А получаю я в итоге вот что
    PHP:
    1. //<div>Привет?">:""":":?>?
    и мой скрипт нахрен дальше не идёт
    А если их кто нибудь возьмёт и отправит специально и они поломают мне код... Гет я просто проверяю так.
    Версия php 5.6 у меня....
    --- Добавлено ---
    как не сломалось, наоборот и всё равно продолжает ломаться, просто не идёт дальше скрипт, обрывается на символах...
     
  20. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Я тебе дал ссылку, всё норм работает. Дай свой скрипт. И это, я исправил сообщение:
     
  21. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    PHP:
    1. echo htmlentities($_GET['rout']);
    2.         exit();
    Это весь скрипт
     
  22. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Ну ты эту строку в браузере сам так ввёл? Браузер нормально закодирует, и явно по-другому, поскольку символы вопроса точно должны быть url-кодированы
     
  23. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    А не вот короче, понял скрипт дальше идёт, но он просто тек строку не читает если есть спец символы....
     
  24. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Сделай до этого var_export($_GET), и увидишь, что бразуер просто другие данные передал в итоге.
     
  25. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    Привет?">:""":":?>? да вот всё что он передал
    --- Добавлено ---
    Спасибо, а что за xss атаки ?
    --- Добавлено ---
    это всё сделал вотс

    PHP:
    1.  //Функция экранирующая данные при добавлении
    2.     public function prepareDataBase ($arr) {
    3.         $db = Db::getConnection();
    4.  
    5.         $stringIns = [];
    6.  
    7.         foreach ($arr as $key => $value) {
    8.             $stringIns[] = sprintf('%s=%s', $key, $db->quote($value));
    9.         };
    10.  
    11.         return $stringIns = implode(', ', $stringIns);
    12.     }
    13.  
    14.     //Функция добавления данных в таблицу БД
    15.     public function Insert($arr) {
    16.  
    17.         $db = Db::getConnection();
    18.  
    19.         $stringIns = $this->prepareDataBase($arr);
    20.  
    21.         $result = $db->query($this->Insert . $this->tableName . ' SET ' . $stringIns);
    22.  
    23.  
    24.     }
    25.  
    26.  
    27.     //Функция обновления данных в таблице БД
    28.  
    29.     public function Update($arr, $where = NULL) {
    30.  
    31.         $db = Db::getConnection();
    32.  
    33.         $stringUp = $this->prepareDataBase($arr);
    34.  
    35.  
    36.         if ($where != Null) {
    37.             $this->where = $this->whereIs($where);
    38.  
    39.         }
    40.  
    41.         $result = $db->query($this->Update . $this->tableName . ' SET ' . $stringUp . $this->where);
    42.  
    43.     }
    --- Добавлено ---
    Я хочу чтобы если что - то через редактор например добавляется. Чтобы проходило через скрипт на сквозь как вписали. Но при этом серверный скрипт ни как не затронуло и базу не потревожило.