mysql_real_escape_string, стрипы и htmlspecialchars

Когда я отправляю переменную в базу данных, я, конечно, использую mysql_real_escape_string. Таким образом, специальные символы идут в базу данных как положено.

Когда я читаю эту переменную из базы данных, я снова использую mysql_real_escape_string вместе с stripslashes:

$var = stripslashes(mysql_real_escape_string($record['rowname']));

иначе это даст мне косую черту перед кавычками.

Когда я использую этот $var, о котором я упоминал выше, и хочу повторить его, я просто могу echo "$var", потому что он уже был удален и экранирован, верно?

Кроме того, если я использую stripslashes + mysql_real_escape_string для переменной, то POST этой же переменной снова в базе данных, достаточно ли mysql_real_escape_string? Или мне нужно снова stripslashes эту переменную?

Обобщая:

Насколько я знаю, как это работает:

  1. используйте mysql_real_escape КАЖДЫЙ раз при использовании данных с mysql: при чтении запроса через переменные так же, как отправка переменных в базу данных.
  2. Используйте stripslashes при отображении экранированных переменных.
  3. Если вы хотите снова опубликовать stripslashes и escape-переменные в базе данных, вам не нужно снова удалять их.

Я скучаю по htmlspecialchars?

ИЗМЕНИТЬ

Значит, это все неправильно?

    while( $record=mysql_fetch_array($result) ) 
    {
        $custid=mysql_real_escape_string($record['custid']);
        $custsurname=mysql_real_escape_string($record['custsurname']);
        $custmidname=mysql_real_escape_string($record['custmidname']);
        $custforename=mysql_real_escape_string($record['custforename']);
        $custcountry=stripslashes(mysql_real_escape_string($record['custcountry'])); }

person TMNuclear    schedule 23.11.2012    source источник
comment
Подождите, пока все люди будут говорить вам переключиться на PDO и подготовить заявления xD, и они правы. прекратите использовать mysql_, так как он устарел и менее безопасен   -  person aleation    schedule 23.11.2012
comment
stackoverflow.com/ вопросы/12859942/ :)   -  person j0k    schedule 23.11.2012
comment
Я знаю, что PDO лучше, но поскольку я почти закончил свое практическое обучение и мне просто нужно навести порядок, я хочу быть уверен, что сделал это хорошо.   -  person TMNuclear    schedule 23.11.2012
comment
Вы не должны использовать mysql_* даже для обучения: он устарел и будет удален в будущих версиях PHP. Используйте PDO или mysqli, подготовленные операторы и filter_var для правильной проверки/санации ввода.   -  person Benjamin Dubois    schedule 23.11.2012
comment
Используйте mysqli или PDO Лично я предпочитаю PDO mysqli из-за поддержки именованных параметров.   -  person    schedule 10.02.2013


Ответы (2)


Боюсь, вы делаете это неправильно. Ключевым моментом является то, что экранирование зависит от контекста, и вы полностью игнорируете этот факт.

В каждом формате данных есть слова или символы, которым в спецификации формата присваиваются специальные значения. Например, символ ' в SQL означает «разделитель строк», символ ? в URL означает «начальная строка запроса», а символ < в HTML означает «начальный тег». Вам нужно экранировать, когда вы хотите вставить буквальное слово или символ, то есть вы хотите вставить его как есть и удалить его особое значение.

Зная это, становится ясно, что синтаксис варьируется в зависимости от формата и контекста. < означает «начальный тег» в HTML, но не в SQL или URL-адресах. Таким образом, вам нужно использовать метод экранирования, созданный для целевого формата и соответствующий правилам формата.

Если вы делаете mysql_real_escape_string() для чтения данных из базы данных, вы говорите: «Скрыть мои данные, чтобы их можно было вставить как внутри строки SQL». Ваши данные готовятся к использованию внутри в виде строки SQL, но искажаются для любого другого использования.

В этом примере случается так, что stripslashes() отменяет большую часть того, что сделал mysql_real_escape_string(), поэтому в итоге вы получаете практически неизмененный результат. Но это чистая случайность.

И последнее, но не менее важное: необходимость экранировать входные параметры базы данных один за другим очень раздражает. Все другие расширения БД, кроме используемого вами1, предлагают подготовленные операторы. Не зацикливайтесь на устаревшем расширении, которое не предлагает современные функции.

1 Примечание: устаревшее расширение mysql устарело в течение нескольких лет, когда стали доступны лучшие альтернативы, и оно больше не является частью языка.

Обновление: небольшое пояснение: экранирование — это всего лишь синтаксический трюк. Вы не изменяете ввод для глаз целевого движка, который просто видит исходные данные как есть. Таким образом, нет необходимости отменять экранирование ввода при его извлечении.

person Álvaro González    schedule 23.11.2012

Вам не нужно stripslashes или mysql_real_escape_string данные, поступающие из базы данных, вам просто нужно экранировать их перед запросом, чтобы синтаксический анализатор запросов знал, что такое специальные символы и что такое буквальные символы.

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

$data_safe = mysql_real_escape_string( $data );
//$data can still be used normally

Экранирование предназначено только для определенного контекста, если контекст представляет собой запрос mysql, тогда вы действительно покинете mysql только для запроса и ничего больше. Если контекст представляет собой вывод в формате html, вы будете использовать htmlescape непосредственно перед выводом строки в формате html. Ни в коем случае вы не хотите фактически изменять сами данные. Если вы неправильно это понимаете, вы увидите O\'Brian и O&#39;Brian и т. д.

person Esailija    schedule 23.11.2012
comment
@IvanM, потому что вы делаете что-то не так, ставите волшебные кавычки или повторяете экранированную переменную sql - person Esailija; 23.11.2012
comment
@IvanM прочитайте первое предложение моего ответа, вы не избегаете данных mysql, поступающих из базы данных, если только вы не собираетесь использовать их в запросе сразу после этого. Вы повторяете их на html-странице, контекст, в котором нет экранирования sql. Возьми? - person Esailija; 23.11.2012