Php экранирование строки. Вопрос: Заменить все кавычки в строке с экранированными кавычками? php символ двойных и одинарных кавычек

2007.11.08 16:07

Столкнулся с проблемой автоматического добавления кавычек в PHP при вводе информации в базу данных.

Немного покопавшись в интернете обнаружил, что проблему можно решить, изменив настройки сервера с помощью директив в.htaccess: magic_quotes_gpc и magic_quotes_runtime.

Говорят (и я этому даже верю), что разработчики языка php, будучи не в силах заставить основную массу php-программистов писать качественный код, решили позаботиться о безопасности наших СУБД и ввели автоматическое добавление слэшей перед спецсимволами. Слэши добавляются на основании директив php.ini (magic_quotes_gpc и magic_quotes_runtime).

Директивы имеют общее название "волшебные кавычки", я же зову их “адские кавычки”. Действительно, в грамотно написанном приложении необходимость в автоматическом закавычивании отсутствует, более того: лишние кавычки мешают, и их приходится удалять.

Первая директива - magic_quotes_gpc - означает, что PHP автоматически добавляет слэши к данным, пришедшим от пользователя - из POST-, GET-запросов и cookies. Вторая переменная - magic_quotes_runtime - означает, что слэши добавляются к данным, полученным во время исполнения скрипта - например, из файла или базы данных. Так, некоторые функции, представляющие подобную информацию, выполняют ее закавычивание.

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

В этой краткой статье показано, как и где стоит использовать кавычки в PHP .

Одинарные кавычки (апострофы) в PHP

Строки, заключенные в одинарные кавычки, никак не обрабатываются PHP. То есть одинарные кавычки представляют текст, заключенный между ними, как есть.

// Правильно echo "Как жизнь?"; echo "Как жизнь? $name"; echo "Как жизнь? ".$name; // Неправильно echo "Как жизнь? $name";

Специальные символы в одинарных и двойных кавычках

Чтобы, например, символ табуляции (\t) интерпретировался как символ табуляции, а не как слеш и буква t, необходимо заключать строку с текстом, в которой содержится символ табуляции, в двойные кавычки. В одинарных кавычках можно использовать только \’ и \\ . Все остальные экранирующие последовательности (\n , \r , \$ и т.д.) недопустимо использовать в одинарных кавычках.

// Неправильно echo "Как жизнь? \n"; // Правильно echo "Как жизнь? \n";

Чтобы экранировать двойные кавычки внутри строки, поставьте кавычки перед обратным слэшем \" .

// Неправильно echo " Как жизнь?"; // Правильно echo " Как жизнь?"; echo " Как жизнь?";

Двойные кавычки в PHP

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

$query = "INSERT INTO table (post,author,text,date) VALUES ("$id","$author","$text","$date")";

Строки в PHP обрамляются одинарными или двойными кавычками. Главное различие в том, что в двойные кавычки можно подставить переменную:

Теперь мы можем придумать ещё одно решение задачи из урока Переменные в PHP :

Как PHP находит переменную в строке?

Всё просто. Помните, какие символы могут использоваться в названии переменной? Это цифры, буквы и подчёркивание _ .

Вот PHP и принимает за название всё, что находится между символом $ и первым запрещённым символом.

В следующем коде PHP неправильно определит название переменной и выдаст ошибку:

Результат в браузере:

Notice: Undefined variable: priceруб in D:\OpenServer\domains\сайт\index.php on line 3

Чтобы PHP правильно определил название переменной в строке, нужно поместить её в фигурные скобки {} :

Результат в браузере:

1499руб

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

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

Экранирование кавычек

Если вам нужно поместить кавычки внутрь строки, есть 2 способа это сделать:

Во втором примере обратный слеш \ экранирует следующую за ним кавычку, чтобы PHP воспринял её как строку.

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


Если ваши пользователи будут хорошими и добрыми, то они будут размещать цитаты старых философов, а сообщения будут иметь примерно следующий вид:

Posted by Plato on January 2, 15:31

I am said to have said "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."


Если пользователи будут умниками, то они, наверное, будут говорить о математике, и сообщения будут такие:

Posted by Pascal on November 23, 04:12

Basic math tells us that if x < n and y > n, x cannot be larger than y.


Хм... Опять эти осквернители наших скобок. Ну, с технической точки зрения они могут быть неоднозначными, но браузер простит нам это, правда?


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

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

Что? Что говоришь, мальчишка? Ах, ты говоришь, "экранирование"? И ты абсолютно прав, возьми печеньку!
Если мы применим экранирование к пользовательским данным до объединения их с запросом, то проблема решена. Для наших запросов к БД это будет что-то вроде:
$name = $_POST["name"]; $name = mysql_real_escape_string($name); $query = "SELECT phone_number FROM users WHERE name = "$name""; $result = mysql_query($query);
Просто одна строка кода, но теперь больше никто не может "взломать" нашу базу данных. Давайте снова посмотрим как будут выглядеть SQL-запросы, в зависимости от ввода пользователя:
Alex
SELECT phone_number FROM users WHERE name = "Alex"
Mc"Donalds
SELECT phone_number FROM users WHERE name = "Mc\"Donalds"
Joe"; DROP TABLE users; --
SELECT phone_number FROM users WHERE name = "Joe\"; DROP TABLE users; --"
mysql_real_escape_string без разбора помещает косую черту перед всем, у чего может быть какое-то особое значение.


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

Posted by JackTR on July 18, 12:56


Обратите внимание, что значения, полученные от пользователи, на самом деле не "повреждены". Любой браузер парсит этот как HTML и выведет на экран все в правильной форме.

Что возвращает нас к... Все вышеупомянутое демонстрирует проблему, характерную для многих систем: текст в тексте должно быть подвергнут экранированию, если предполагается, что он не должен иметь специальных символов. Помещая текстовые значения в SQL, они должны быть экранированы по правилам SQL. Помещая текстовые значения в HTML, они должны быть экранированы по правилам HTML. Помещая текстовые значения в (название технологии), они должны быть экранированы по правилам (название технологии). Вот и все.Для полноты картины Есть, конечно, другие способы борьбы с пользовательским вводов, который должен или не должен содержать специальные символы:
  • Validation
    Вы можете проверить, соответствует ли пользовательский ввод некоторой заданной спецификации. Если Вы требуете ввода числа, а пользователь вводит нечто другое, программа должна сообщить ему об этом и отменить ввод. Если все это правильно организовать, то нет никакого риска схватить "DROP TABLE users" там, где, предполагалось, пользователь введет "42". Это не очень практично, для избегания HTML/SQL-инъекций, т.к. часто требуется принять текст свободного формата, который может содержать "подковырки". Обычно валидацию используют в дополнение к другим мерам.
  • Sanitization
    Вы можете так же "втихую" удалить любые символы, которые считаете опасными. Например, просто удалить что-либо похожее на HTML-тег, что избежать добавления на ваш форум. Проблема в том, что вы можете удалить вполне законные части текста.
    Prepared SQL statements
    Есть специальные функции, делающие то, чего мы и добивались: заставляют БД понять различия между самим SQL-запросом и информацией, предоставленной пользователями. В РНР они выглядят примерно так:
    $stmt = $pdo->prepare("SELECT phone_number FROM users WHERE name = ?"); $stmt->execute($_POST["name"]);
    При этом отправка происходит в два этапа, четко разграничивая запрос и переменные. БД имеет возможность сначала понять структуру запроса, а потом заполнить его значениями.

  • В реальном мире, все это используется вместе для различных ступеней защиты. Вы должны всегда использовать проверку допустимости (валидацию), чтобы быть уверенным, что пользователь вводит корректные данные. Затем вы можете (но не обязаны) сканировать введенные данные. Если пользователь явно пытается "втюхать" вам какой-то скрипт, вы можете просто удалить его. Затем, вы всегда, всегда должны экранировать пользовательские данные прежде, чем поместить их в SQL-запрос (это же касается и HTML).