Посидел над скриптиком безопасности.Кто соображает больше-дайте совет! Код (Text): <?php session_start(); include ("bd_hell.php"); if (!empty($_POST['login']) and !empty($_POST['name'])) { $login = mysql_real_escape_string(trim($_POST['login'])); $login = htmlspecialchars($login); if(get_magic_quotes_gpc()) { $login = stripslashes($login); } $pass = mysql_real_escape_string(trim($_POST['pass'])); $pass = htmlspecialchars($pass); if(get_magic_quotes_gpc()) { $pass = stripslashes($pass); } if(!preg_match("/^[a-zA-Z0-9_\.\-]$/",$login)) { header("Location: index.html"); } else { if(!preg_match("/^[a-zA-Z0-9_\.\-]$/",$pass)) { header("Location: index.html"); } else { $sql = "SELECT * FROM `userlist` WHERE `login`='$login' AND `pass`='$pass' LIMIT 1"; $result = mysql_query($sql, $db)or die("Ошибка в запросе: " . mysql_error()); if (!$result) { echo "ошибка - ".mysql_error()."<br>"; echo $sql; exit(); } else { $myrow = mysql_fetch_assoc($result); if(!empty($myrow['id'])) { $_SESSION['id'] = $id; header("hell.php"); } else { header("Location: index.html"); } } } } } else { header("Location: index.html"); } if (isset($_SESSION['id'])) { $id = intval(mysql_real_escape_string($_SESSION['id'])); if (!preg_match("|^[\d]+$|", $id)) { header("Location: index.html"); } else { $login = mysql_real_escape_string(trim($_SESSION['login'])); $login = htmlspecialchars($login); if(get_magic_quotes_gpc()) { $login = stripslashes($login); } $pass = mysql_real_escape_string(trim($_SESSION['pass'])); $pass = htmlspecialchars($pass); if(get_magic_quotes_gpc()) { $pass = stripslashes($pass); } $sql = "SELECT * FROM `userlist` WHERE `login`='$login' AND `pass`='$pass' LIMIT 1"; $result = mysql_query($sql, $db)or die("Ошибка в запросе: " . mysql_error()); if (!$result) { echo "ошибка - ".mysql_error()."<br>"; echo $sql; exit(); } else { $myrow = mysql_fetch_assoc($result); if(empty($myrow['id'])) { header("Location: index.html"); } } } else { header("Location: index.html"); } ?> В частности у меня выдаёт ошибки: Код (Text): Warning: session_start() [function.session-start]: Cannot send session cookie - headers already sent by (output started at Z:\home\localhost\www\rosneft\enterAd.php:1) in Z:\home\localhost\www\rosneft\enterAd.php on line 2 Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at Z:\home\localhost\www\rosneft\enterAd.php:1) in Z:\home\localhost\www\rosneft\enterAd.php on line 2 Warning: Cannot modify header information - headers already sent by (output started at Z:\home\localhost\www\rosneft\enterAd.php:1) in Z:\home\localhost\www\rosneft\enterAd.php on line 56 Warning: Cannot modify header information - headers already sent by (output started at Z:\home\localhost\www\rosneft\enterAd.php:1) in Z:\home\localhost\www\rosneft\enterAd.php on line 99 Спасибо за потраченное время...
Во-первых, если хочешь учесть то, что на сервере возможно включены magic_quotes_gpc, то делаешь это не в той последовательности. Сперва нужно проверить и сделать stripslashes при необходимости, а потом уже делать mysql_real_escape_string(). Во-вторых, чтобы не повторять этот фрагмент кода для каждого параметра запроса - можно, например, написать функцию, которая будет это делать: Код (PHP): <?php function myEscape($str = '') { if(get_magic_quotes_gpc()) $str = stripslashes($str); return(mysql_real_escape_string($str)); } ?> и потом просто ей всё эскейпить: Код (PHP): <?php // ... $login = myEscape($_POST['login']); // ... ?> В-третьих, через htmlspecialchars() обычно пропускают не при записи в б.д., а при выводе из б.д. в браузер. В принципе, это не принципиально я думаю, но обычно так делают - типа чтобы в б.д. хранились оригинальные данные, какими их ввёл пользователь. В-четвёртых, проверку на допустимые в логине символы (a-zA-Z0-9_.-) - это на мой (и не только мой) взгляд лишнее. Мне кажется, пусть пользователи называют себя как им нравится. Хотят русскими буквами - ну и пусть русскими пишут, какя разница? Но это дело твоё, конечно. Для безопасности роли не играет по идее. В-пятых, после того, как делаешь переадресацию header Location - нужно учитывать, что отправив этот заголовок скрипт будет выполняться дальше. Да, в браузере страница не отобразится, но скрипт отработает до конца и выполнятся все инструкции, которые там дальше идут. Например, что-то может добавиться в б.д., если там есть вставка данных. Для php команда header('Location: index.html'); - это как и любая другая обычная команда, тот же echo(), например. Он выполнит её (отправит заголовок браузеру) и продолжит дальше выполнять следующие команды. Если ты хочешь, чтобы после отправки заголовка на переадресацию дальше скрипт не выполнялся - нужно после header ставить exit; Код (PHP): if(!preg_match("/^[a-zA-Z0-9_\.\-]$/",$pass)) { header("Location: index.html"); exit; } В-шестых, тримить (trim()) пароль я лично бы не стал - может пользователь хочет, чтобы его пароль начинался с пробела? Ну и пусть начинается с пробела. Зато в б.д. принято писать хэш пароля, а не в чистом виде. Впрочем, это скорее всего, тоже мелочи и не принципиально, но обычно делают так. Причём как правило не просто стандартный хэш типа md5, а что-то вроде хэш от хэша с солью Ну как-то так, например: Код (PHP): $salt = 'Это соль :-)'; $pass = md5(md5($_POST['pass']) . $salt); В-седьмых, вот это вот: Код (PHP): or die("Ошибка в запросе: " . mysql_error()); на рабочем сайте в интернете - вообще ни к чему. Это нужно на период разработки и отладки скрипта. Когда скрипт готов и выложен в интернет - в нём не должно быть такого. Я знаю две причины: одна из них - это то, что это просто какая-то лишняя, пугающая и не понятная пользователям информация, которая к тому же никак не оформлена, а просто сверху появятся чёрные буквы на белом фоне. Пользователю это уж точно не надо Во вторых, это может здорово облегчить жизнь потенциальным взломщикам твоего сайта. Особенно вместе вот с этим: Код (PHP): echo "ошибка - ".mysql_error()."<br>"; echo $sql; exit(); Увидев текст получившегося запроса и сообщение об ошибке, подобрать заветную фразу чтобы всё поломалось окончательно будет легче Добавлено спустя 14 минут 59 секунд: Я обычно пишу свою функцию, которая вызывается, если запрос не прошёл, и передаю ей три аргумента: текст запроса, текст сообщения об ошибке и третьим параметром - нужно ли останавливать работу скрипта: Код (PHP): function db_error($sql = '', $err = '', $stop = false) { if(Config::$debug_mode) { // Режим отладки. Вываливаем сообщение об ошибке запроса на экран } else { // Рабочий режим. // Здесь мы записываем информацию о произошедшей ошибке в лог // И проверяем, нужно ли останавливать выполнение скрипта if($stop) { require('site_error.html'); exit; } } } Соответственно, вызываться может так: Код (PHP): $sql = "SELECT * FROM `users`"; $res = mysql_query($sql, $db) or db_error($sql, mysql_error($db), true); В данном случае я посчитал, что это был важный запрос, без которого дальнейшее выполнение скрипта бессмысленно. Поэтому я передаю третьим параметром true - чтобы функция вывела на экран содержимое файла site_error.html и остановила выполнение скрипта. В файле site_error.html может храниться какая-нить оформленная и задизайненная страничка с сообщением о том, что на сайте что-то произошло. Там могут быть какие-то полезные ссылки - например, перейти на главную, вернуться назад или отправить письмо админу сайта. Добавлено спустя 3 минуты 47 секунд: UPD! Блин, правку отключили В общем я там в функции db_error() не правильно написал. Надо было так: function db_error($sql = '', $err = '', $stop = false) { if(Config::$debug_mode) { // Режим отладки. Вываливаем сообщение об ошибке запроса на экран } else { // Рабочий режим. // Здесь мы записываем информацию о произошедшей ошибке в лог // И проверяем, нужно ли останавливать выполнение скрипта if($stop) { require('site_error.html'); } } if($stop) exit; } Добавлено спустя 1 минуту 47 секунд: И опять блин, правку отключили )) Код (PHP): function db_error($sql = '', $err = '', $stop = false) { if(Config::$debug_mode) { // Режим отладки. Вываливаем сообщение об ошибке запроса на экран } else { // Рабочий режим. // Здесь мы записываем информацию о произошедшей ошибке в лог // И проверяем, нужно ли останавливать выполнение скрипта if($stop) { require('site_error.html'); } } if($stop) exit; } Добавлено спустя 3 минуты 38 секунд: А по поводу твоей ошибки - это говорит о том, что где-то уже начат вывод страницы, а ты пытаешься отправить заголовок. Например, такое может быть, если файл со скриптом сохранён в кодировке UTF-8 с BOM (надо сохранить в UTF-8 без BOM). Также такое может выскочить, если где-то перед <?php есть какой-нибудь символ, который ты не заметил - достаточно одного пробела.
Ох!!!Вот это ответ...тут и добавить нечего уже!Спасибо большое!!! Только вот вопрос:что это вообще такое - BOM!!!Я пробовал без BOM сохранять и у меня тогда вместо русских букв иероглифы...
Код (PHP): public static function injects($injects,$bool=false) { if(self::$mysqli && !$bool) { return mysqli_real_escape_string(self::$mysqli,$injects); } else if(version_compare(PHP_VERSION,'5.3.0','<')) { return get_magic_quotes_gpc()?$injects:addslashes($injects); } else { return addslashes($injects); } return false; } Ну еще можно таким путем пойти.
это же срань господня! "без BOM не работает" )))) во первых убедись, что твой файл таки в UTF-8 сохранился, а не в какой-нибудь 1251 во вторых проверь что браузер получает заголовок Код (Text): Content-Type: text/html; charset=UTF-8
Your,спасибо,применяю к работе! artoodetoo,да в utf-8,проверял 1000 раз!Щас ещё поковыряю... Так в чём разнице между с BUM т без BOM? Всё сделал как Вы советовали:пользователь вводит логин и пароль-передаётся обработчику,который если "плохо",то на index.html,а если нормально,то на нужную страницу-на нужной страницу проверяю: Код (Text): if (isset($_SESSION['id'])) ,но всё время проверяет условие "else"-как быть?В чём причина может скрываться?
а на "нужной странице" до этой строки вызывается session_start() ? иногда дурацкие вопросы не такие уж и дурацкие
http://ru.wikipedia.org/wiki/BOM В общем это такой спецсимвол, который текстовый редактор поставит самым-самым первым в файле, он-то и начнёт отправку основного содержимого ответа ещё до того, как ты заголовки пытаешься отправить.