|
|
|
| Подскажите пожалуйста как все таки правильно экранировать данные при использовании их в SQL запросах. Стоит ли делать вот так:
$name=htmlspecialchars(stripslashes(trim(mysql_escape_string($login))));
|
или это лишние предосторожности? В общем как правильно подготовить строку str для записи в базу данных MySQL? | |
|
|
|
|
|
|
|
для: aalexx
(12.03.2006 в 18:46)
| | Нет так делать не стоит хотя бы из-за того, что на сервере может быть включён режим магических кавычек, да и сама последовательность функций
stripslashes(mysql_escape_string($login))
|
имеет нулевой эффект.
Для экранирования следует применять конструкцию
<?php
if (!get_magic_quotes_gpc())
{
$name = mysql_escape_string($name);
}
?>
|
Кроме этого, функцию htmlspecialchars() обычно применяют не до помещения в базу данных, а перед выводом из базы данных на страницу. Иначе, если потребуется редактирование информации - будет сложно работать. | |
|
|
|
|
|
|
|
для: aalexx
(12.03.2006 в 18:46)
| | так делать не стоит ни в коем случае. Надо четко представлять себе,
1. В каком виде данные попадают скрипту на вход.
2. В каком виде данные нужно передать туда, куда мы их отправляем
Попытка применить скопом несколько снадобий только увеличит риск sql-injection-уязвимости и/или других видов атак.
1. Если данные на вход скрипту приходят из get/post/cookie параметров, их скорее всего успел подвергнуть экранированию кавычек нуля и обратных слэшей сам движок PHP. Или не успел. Зависит от настройки PHP, известной под названием magic_quotes_gpc . Чтобы убрать неопределенность, надо проверить настройки, и при необходимости удалить зазря понаставленные слэши:
<?
$login = $_POST['login']; // Берем занчение параметра
if(get_magic_quotes_gpc()) // если включен режим magic_quotes
$login = stripslashes($login); // то удалим слэши, добавленные PHP
?>
|
На этом месте с параметром можно работать, как с любой другой переменной, хранящей строковое значение.
2. В дальнейшей работе параметр нужно экранировать, применяя правило экранирования для того языка, где этот параметр будет применяться. Но лишь одно правило, а не все скопом.
Если параметр нужно использовать в mysql-запросе, как строковый литерал, то его надо взять в кавычки.
Но написать просто $login = ""'$login'"; мы не можем. Вот здесь идет самый важный логический шаг. Мы должны использовать экранирование вовсе не потому, что боимся sql-инъекции, а потому что синтаксис SQL-языка предписывает некоторые символы в строковых литералах предварять слэшами:
<?
$query = "insert into users (login) values('".mysql_escape_string($login)."'";
?>
|
или
<?
$query = "select name from users where login='".mysql_escape_string($login)."'";
?>
|
Если значение нужно передать, как часть параметра url, его нужно экранировать. Но опять же, вовсе не потому, что мы боимся вредноносных javascript-вставок, а потому, что значение в URL пишется на некотором языке (RFC--1738) со своими правилами замены пробелов, символов национальных алфавитов и некоторых других спецсимволов.
<?
$url = "info.php?login=".urlencode($login);
?>
|
Если и будет в логине какой хитрый знак, он все-равно попадет в параметр, а не выйдет из-под контроля.
Теперь допустим , что этот url нужно сделать частью ссылки: <a href="url">login</a>
Сперва разбираемся с тегом <a> и его атрибутом href. Согласно спецификации языка html, текстовые значения атрибутов , обрамляются двойными кавычками, а сами двойные кавычки, содержащиеся в значении расписываются html-сущностями. Ими же распиывается знак амперсенда, и угловые скобки. Для этого применяется функция htmlspecialchars():
<?
$href = 'href="'.htmlspecialchars($url).'"';
?>
|
Внутри тега <a>, где нам нужно поместить логин, действуют те же правила записи html-символов.
Чтобы от языка текст перейти к языку html, нужно спецсимволы html-языка (кавычки, угловые скобки, амперсанд ) закодировать соответствующими html-сущностями. Для этого применяем htmlspecialchars():
<?
$reference = "<a $href>" . htmlspecialchars($login) . "</a>";
?>
|
И в таком виде уже можем выкинуть в выходной поток.
Теперь, наконец, допустим, что текст этой ссылки нам нужно не просто вывести, а передать в JavaScript, как значение некоей переменной ref. Правила записи строковых литералов JavaScript требуют заэкранировать кавычки и обратные слэши и обрамить полученное кавычками. Реализуется это с помощью addslashes():
<?
$js_str = "'".addslashes($reference)."'";
echo "<script language=javascript>var ref = $js_str; document.writeln(ref);</script>";
?>
|
Важно четко понимать, что применять функции экранирования следует по одной, и именно там, где происходит переход от одного языка к другому. И применять именно ту функцию, которая согласует один язык с другим. В противном случае, возможны бреши в защите. | |
|
|
|
|
|
|
|
для: Trianon
(12.03.2006 в 20:07)
| | Спасибо огромное, по моему исчерпывающий ответ! Господа Модераторы, предлагаю сделать из этого поста статью и смело поместить ее в список статей на Вашем сайте. Уверен что 90% начинающих РНР программистов либо тупо делают именно так как было показанно в моем примере (кстати пример я взял в одной из тем не этом форуме, так что судите сами :)) либо вообще не знают что и как надо делать.
Есть еще вопрос. Если поле в таблице ну скажем утановленно как varchar(10), а мне нужно записать туда строку из 10 символов содержащую спецсимволы (например кавычки "") после экранирования добавив слэши не произойдет ли ошибка при записи в базу данных (строка то уже получится не 10 а 12 символов)? | |
|
|
|
|
|
|
|
для: aalexx
(13.03.2006 в 11:14)
| | Есть значение поля длиной 10 и есть литеральное представление значения этого поля длиной 12 или даже 20 (для десяти кавычек например). Контролируется именно длина значения.
Попробуйте выполнить следующий код:
CREATE TABLE tab ( text char(3) NULL );
INSERT INTO tab (text) VALUES ('abc'), ('\'\\\"'),('defghi');
SELECT * FROM tab;
|
На выходе будет:
| |
|
|
|
|
|
|
|
для: Trianon
(13.03.2006 в 11:36)
| | т.е. Вы хотите сказать что движок просто обрезает строку если она не совпадает по длинне со значением заданным в поле базы данных? =-О или всетаки выдается ошибка записи? | |
|
|
|
|
|
|
|
для: aalexx
(13.03.2006 в 11:45)
| | Я хочу сказать, что применение литерала (апостроф слэш апостроф слэш слэш слэш кавычка апостроф) длиной 8 знаков с учетом обрамления, представляющего текст (апостроф слэш кавычка) длиной 3 знака привело к тому, что текст был внесен в поле шириной 3 символа безо всяких искажений. Несмотря на Ваши опасения. А применение литерала 'defghi' той же длины, представляющего текст длиной 6 символов, повлекло обрезание текста до размера поля.
Как именно реагирует СУБД на попытку внести слишком длинный текст - диагностикой ошибки, усечением текста или раздуванием поля - вопрос совсем другой. | |
|
|
|
|
|
|
|
для: Trianon
(13.03.2006 в 11:54)
| | Понятно спасибо! | |
|
|
|
|
|
|
|
для: Trianon
(12.03.2006 в 20:07)
| | - | |
|
|
|