PHP mysql_real_escape_string() -> stripslashes() оставляет несколько косых черт

У меня возникают проблемы с экранированием/удалением строк с помощью PHP/MySQL - кажется, что всегда есть избыточные косые черты.


В качестве примера возьмем следующую строку:

<span style="text-decoration:underline;">underline</span>


При добавлении строки в базу данных я экранирую ее с помощью mysql_real_escape_string(), и в базе данных сохраняется следующее (EDIT: проверил это, запросив базу данных напрямую с помощью приложения mysql):

<span style=\\\"text-decoration:underline;\\\">underline</span>


При обратном чтении из базы данных я передаю строку через stripslashes(), и возвращается следующее:

<span style=\"text-decoration:underline;\">underline</span>


Так как кавычки все еще экранированы, это ломает html и текст не подчеркивается.


  1. Почему mysql_real_escape_string() добавляет три косые черты, а stripslashes() удаляет две косые черты? Я бы ожидал, что они оба добавят/удалит одну косую черту.
  2. Как я могу предотвратить это?
  3. Правильно ли я подхожу к этому?

person teaforchris    schedule 05.10.2009    source источник
comment
Примечание: mysql()*устарел с PHP 5.5.0, его не рекомендуется использовать для написания нового кода, так как он будет удален в будущем. вместо этого используйте либо mysqli, либо PDO   -  person    schedule 10.02.2013


Ответы (3)


Лучшее решение

Скорее всего, в вашем файле php.ini включена директива magic_quotes_gpc. Это должно быть отключено из соображений безопасности. Если у вас нет доступа к файлу php.ini (например, на общем хосте), вы всегда можете сделать то же самое с помощью директивы .htaccess (при условии, что это сервер Apache).

В вашем php.ini

magic_quotes_gpc Off

В файле .htaccess:

php_flag magic_quotes_gpc Off

Почему это происходит?

Причина, по которой это происходит, связана со следующим ходом логики.

  1. A string that needs escaping is sent to the server.
    • This is my string. It's awesome.
  2. Magic Quotes escapes the apostrophe before it gets to your code.
    • This is my string. It\'s awesome
  3. mysql_real_escape_string now has two characters to escape, the backslash \\ as well as the apostrophe \'.
    • This is my string. It\\\'s awesome
  4. Эта новая строка с суперэкранированием сохраняется в базе данных.
  5. When the string is retrieved from the database, it get's passed to stripslashes. This removes the two escapes added in step 3, but since one of the backslashes has been escaped stripslashes thinks it belongs.
    • This is my string. It\'s awesome

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

Альтернативное решение

Быстрая и простая альтернатива — просто удалить косые черты, добавленные magic_quotes, перед передачей строки mysql_real_escape_string.

$str = stripslashes($_POST['str']);
$str = mysql_real_escape_string($str);
person TJ L    schedule 05.10.2009
comment
Эта проблема действительно может выйти из-под контроля, когда вы повторно отправляете эти строки в базу данных, так как каждый раз количество обратных косых черт увеличивается. Да, это начало происходить! - person teaforchris; 06.10.2009
comment
Фантастический ответ, проблема решена. Спасибо, что рассмотрели логику относительно того, откуда взялись три косые черты, теперь это имеет смысл. - person teaforchris; 06.10.2009

При добавлении строки в базу данных я экранирую ее с помощью mysql_real_escape_string(), и в базе данных сохраняется следующее:

<span style=\\\"text-decoration:underline;\\\">underline</span>

Нет, это не так. Когда вы экранируете строки в запросе sql, это только для передачи данных в запросе. База данных анализирует запрос и сохраняет данные в базе данных без лишних косых черт. Таким образом, когда вы извлекаете данные из базы данных, вы не должны ничего не распаковывать. Это распространенное заблуждение.

Если вы обнаружите, что в выводе есть лишние косые черты, возможно, у вас включены волшебные кавычки. Отключите их.

Редактировать:

mysql> create table foo (bar text) ;
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO foo (bar) VALUES ("<span style=\\\"text-decoration:underline;\\\">underline</span>");
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM foo;
+-------------------------------------------------------------+
| bar                                                         |
+-------------------------------------------------------------+
| <span style=\"text-decoration:underline;\">underline</span> | 
+-------------------------------------------------------------+
1 row in set (0.00 sec)

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

person troelskn    schedule 05.10.2009
comment
Я выполнил SQL-запрос с помощью приложения MySQL непосредственно в базе данных, и указанная выше строка возвращается. Так что мне кажется, что em›is/em› хранится в базе данных с тремя косыми чертами. - person teaforchris; 06.10.2009
comment
Я не знаю точно, что вы имеете в виду, но косая черта используется, потому что вы встраиваете данные в код. Так же, как строковые литералы в исходном коде php. Применяются те же правила. - person troelskn; 06.10.2009
comment
Косые черты должны избегать данных, которые не хранятся в БД. Если вы видите косые черты, значит, они должны быть лишними. - person GL_Stephen; 11.01.2014

Если get_magic_quotes_gpc() отключено в SERVER, то только мы можем использовать

$data= mysql_real_escape_string($_POST['data']);

если get_magic_quotes_gpc() включен в SERVER, мы должны использовать

$data= mysql_real_escape_string(stripslashes($_POST['data']));

в противном случае добавьте две обратные косые черты к своим данным.

Также другое решение: мы можем использовать stripslashes($data) при извлечении из базы данных, если мы используем только использование mysql_real_escape_string($_POST['data']);

person sujay mondal    schedule 06.02.2013
comment
Stripslashes и mysql_real_escape_string нельзя использовать вместе. Первый нужно использовать в самом начале скрипта. чистить ВСЕ данные, а не только те, что идут в БД. В то время как последний нужно использовать непосредственно перед добавлением строки (и только строки!) в запрос. И последнее вообще не решение - person Your Common Sense; 06.02.2013