Доброго времени суток всем. Хочу сделать сайт, сделать не себе. Опыта программирования на php почти нету (5 дней ) и поэтому возможно будут заданы глупые вопросы на которые существуют очевидные ответы. Пис(а)ть буду только сам и только в vim. Есть небольшой опыт программирования на других языках, поэтому разобраться будет легче. На сайте будет админка, доступ будет ограничивать скрипт написанный на php. Начал пис(а)ть этот самый скрипт. Проблем особых не возникло, но боюсь за безопасность: ввиду отсутствия опыта и плохого знания языка могу допустить большое количество ошибок. Хотел бы попросить у вас 1) мельком просмотреть скрипт и ткнуть носом в наиболее серьезные недоделки 2) подсказать, что бы еще добавить для повышения безопасности Основные принципы защиты понятны, но в гуглах море информации и читать ее надо последовательно и разбираться длительное время. Я не против, но время не очень много. А вот сам скрипт: Таблица пользователей: Код (Text): CREATE TABLE `cpusers`( `id` smallint(5) unsigned NOT NULL auto_increment, `login` varchar(20) NOT NULL, `password` char(32) NOT NULL, `salt` char(3) NOT NULL, `priv` tinyint(1) unsigned NOT NULL, primary key(`id`), unique key (`login`) ) type=MyISAM; Конфиг: Код (Text): <?php # корень сайта для проверки рефера define("SERVERROOTI" , "http://127.0.0.1/"); define("SERVERROOTD" , "http://localhost/"); # опции соединения базой define("MYSQLHOST" , "localhost"); define("MYSQLUSER" , "root"); define("MYSQLPASSW" , ""); # основная база define("MYSQLDB" , "main_db"); # таблица пользователей define ("USERSTABLE" , "cpusers"); define("AUTHSID" , "auth_sid"); define("AUTHPAGE" , "index.php"); define("SECRETPAGE" , "cp.php"); define("REGPAGE" , "reg.php"); define("USERADDEDPAGE", "userok.php"); ?> Ошибки: Код (Text): <?php $err=array(); $err[0] = "Поле 'Имя пользователя' не содержит значения."; $err[1] = "Поле 'Пароль' не содержит значения."; $err[2] = "Введенные пароли не совпадают."; $err[3] = "Поле 'Имя пользователя' имеет неверную длину: поле должно содержать не более 20 символов."; $err[4] = "Поле 'Пароль' имеет неверную длину: размер поля не может быть короче 6 символов или длиннее 10."; $err[5] = "Поле 'Логин' имеет неправильный формат: разрешается использовать только буквы латинского алфавита, цифры и символ подчеркивания _. Первым символом должна быть буква."; $err[6] = "Поле 'Пароль' имеет неправильный формат: разрешается использовать только буквы латинского алфавита и цифры."; $err[7] = "Введенное имя пользователя уже существует. Выберите другое имя."; $err[8] = "Неверное имя пользователя или пароль."; ?> Работа с мускулем: Код (Text): <?php function dbConnect($user , $passw , $db , $host='localhost'){ $link = mysql_connect($host , $user , $passw) or die(mysql_error()); mysql_select_db($db , $link) or die(mysql_error()); return $link; } ?> Функции: Код (Text): <?php include("mysql.php"); include_once("conf.php"); #генерирует заданое число случайных символов и возвращает результат в виде строки function generateSalt($n=3){ $key = NULL; $pattern="qwert3y1u2i5op4asd6fg97hjk8lzxc0vbnm"; $max = strlen($pattern) - 1; srand((double) microtime() * 1000000); for($i = 0 ; $i < $n; $i++) $key .= $pattern{rand(0 , $max)}; return $key; } # FUNC проверяем наличие пользователя в базе # возвращаем id в случае успеха и NULL в противном случае function auth($login , $passw){ $link=dbConnect(MYSQLUSER , MYSQLPASSW , MYSQLDB , MYSQLHOST); # экранирование специальных символов $login = mysql_real_escape_string($login); $hash = md5($passw); $query = "SELECT * FROM `".USERSTABLE."` WHERE `login`='".$login."' LIMIT 1;"; # выполняем запрос или выводим ошибку $result = mysql_query($query) or die(mysql_error()); # вычисляем количество строк в результате запроса $num = mysql_num_rows($result); $uid = NULL; # пользователь найден? if($num == 1){ # извлекаем соответствующую ему строку из ирезультата запроса $row = mysql_fetch_row($result); # получаем значения полей $dbUid = $row[0]; $dbHash = $row[2]; $dbSalt = $row[3]; # проверяем совпадение пароля if ($dbHash == md5($hash.$dbSalt)) $uid = $dbUid ; } #mysql_close($link); return $uid; } #endFunc # FUNC регистрирует пользователя в базе # возвращает 1, если пользователь зарегистрирован и 0, если такой пользователь уже существует function reg($login , $passw){ # соединяемся с базой $link = dbConnect(MYSQLUSER , MYSQLPASSW , MYSQLDB , MYSQLHOST); # экранирование спецмальных симолов $login = mysql_real_escape_string($login); $hash = md5($passw); # проверяем существование пользователя $userExists = "SELECT * FROM `" . USERSTABLE . "` WHERE `login`='" . $login . "' LIMIT 1;"; $result = mysql_query ($userExists) or die(mysql_error()); $ret = false; $num = mysql_num_rows($result); # если пользователя нет - регистрируем if($num == 0){ $salt = generateSalt(); $addUser = "INSERT INTO `" . USERSTABLE . "` VALUES(NULL , '" . $login . "' , '" . md5($hash . $salt) . "' , '" . $salt . "' , '0');"; mysql_query($addUser) or die(mysql_error()); $ret = true; } mysql_close($link); return $ret; } ?> Форма ввода данных для авторизации: Код (Text): <?php include("init.php"); include("conf.php"); include("func.php"); include("errors.php"); # задаем имя сессии session_name(AUTHSID); # открываем сессию session_start(); if (!isset($_SESSION['userid'])) $_SESSION['userid'] = NULL; # если пользователь авторизован - редирект if (!is_null($_SESSION['userid'])){ header("location: cp.php"); die; } # генерируем ключ $salt = generateSalt(); # привязка по браузеру и ip $bind = $_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT']; # пишем в сессию $_SESSION['bind'] = md5($bind); $_SESSION['key'] = md5($salt); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Вход в панель администрирования</title> <link rel="stylesheet" type="text/css" href="main.css" /> </head> <body> <form method="POST" action="auth.php" class="auth_form"> <p class="caption"> Заполните поля для авторизации на сервере</p> <p> <label for="ilogin">Имя пользователя</label> <input type="text" name="login" id="ilogin"/> </p> <p> <label for="ipassw">Пароль</label> <input type="password" name="passw" id="ipassw" /> </p> <input type="hidden" name="key" value="<?php echo $_SESSION['key']?>" /> <div> <input type="submit" name="submit" value="ВХОД" /> </div> <p class="error"> <?php # если стоит флаг ошибки - выводим if((isset($_GET['err'])) && ($_GET['err']==1)) echo '* '.$err[8]; ?> </p> </form> </body> </html> Обработка формы авторизации Код (Text): <?php /////////////////////////////////////////////////// /// Авторизация пользователей /// /////////////////////////////////////////////////// include("conf.php"); include("func.php"); $location=AUTHPAGE; if (isset($_COOKIE[AUTHSID])){ # открываем сессию session_name(AUTHSID); session_start(); if (!isset($_SESSION['userid'])) $_SESSION['userid'] = NULL; $err=NULL; ### include("init.php"); # проверяем авторизован ли пользователь if (is_null($_SESSION['userid'])){ # данные были отправлены формой if ((isset($_POST['submit'])) && (isset($_POST['login'])) && (isset($_POST['passw']))) if ((isset($_POST['key'])) && (!is_null($_POST['key'])) && ($_POST['key'] == $_SESSION['key'])){ $ref = $_SERVER['HTTP_REFERER']; # проверяем страницу с которой пришел пользователь if ((strpos($ref , SERVERROOTD) == 0) || (strpos($ref , SERVERROOTI) == 0)){ # сохраняем логин и пароль # логин очищаем от окружающих его пробелов $login = trim($_POST['login']); $passw = $_POST['passw']; if (!((empty($login)) || empty($passw))){ # ищем недопустимые симолы $badLogin = preg_match("/[^a-z,A-Z,0-9,\_]|^[0-9\_]/" , $login); $badPassw = preg_match("/[^a-z,A-Z,0-9]/" , $passw); # усе нормально?? продолжаем... if (!($badLogin || $badPassw)) $uid = auth($login , $passw); if (!is_null($uid)) # авторизуем пользователя $_SESSION['userid'] = $uid; } } # если авторизация не уалась, ставим ошибку if (is_null($_SESSION['userid'])) $err="?err=1"; } } # удаляем ключ, который пользователь получает на главной странице if (!is_null($err)) unset($_SESSION['key']); # параметры редиректа if (!is_null($_SESSION['userid'])) $location = SECRETPAGE; else $location = AUTHPAGE.$err; } # редирект header("location: ".$location); ?> Форма регистрации Код (Text): <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://wwww.w3.org/1999/xhtml" xml:lang="ru" lang="ru"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Регистрация пользователя</title> <link rel="stylesheet" type="text/css" href="main.css" /> </head> <body> <form method="POST" action="adduser.php" class="auth_form"> <p class="caption"> Регистрация нового пользователя </p> <p> <label for="ilogin">Имядля входа(login)</label> <input type="text" size="15" name="login" id="ilogin"/> </p> <p> <label for="ipassw">Пароль</label></td> <input type="password" size="10" name="passw" id="ipassw" /> </p> <p> <label for="irepeatpassw">Пароль(еще раз)</label> <input type="password" size="10" name="repeatpassw" id="irepeatpassw" /> </p> <div> <input type="submit" name="submit" value="Зарегистрировать" /> </div> <p class="error"> <?php include("errors.php"); if ((isset($_GET['errcode'])) && ($_GET['errcode'] >= 0) && ($_GET['errcode'] < 8)){ $errCode=$_GET['errcode']; echo $err[$errCode]; } ?> </p> </form> </body> </html> Обработка формы регистрации: Код (Text): <?php include ("init.php"); include ("conf.php"); include ("func.php"); # проверяем существование переменных if(!( (isset($_POST['login'])) && (isset($_POST['passw']))&& (isset($_POST['repeatpassw'])) && (isset($_POST['submit'])) )){ header("location: " . REGPAGE); die; } # $ref = $_SERVER['HTTP_REFERER']; if (!((strpos($ref , SERVERROOTD) == 0) && (strpos($ref , SERVERROOTI) == 0))){ header("location: " . REGPAGE); die; } # ложим все в локальные переменные $login = trim($_POST['login']); $passw = $_POST['passw']; $repeatpassw = $_POST['repeatpassw']; # код ошибки для возврата форме $errCode = NULL; # пустой логин if(empty($login)) $errCode = 0; else # пустой пароль if(empty($passw)) $errCode = 1; else # пароли несовпадают if($passw != $repeatpassw) $errCode = 2; else # неверная длина логина if(strlen($login) > 20) $errCode = 3; else # неверная длина пароля if((strlen($passw)<6) || (strlen($passw)>10)) $errCode = 4; else # недопустимые символы в логине if(preg_match("/[^a-z,A-Z,0-9,\_]|^[0-9\_]/" , $login)) $errCode = 5; else # недопустимые символы в пароле if(preg_match("/[^a-z,A-Z,0-9]/" , $passw)) $errCode = 6; # если есть ошибки, шлём их на форму вместе с пользователем if (!is_null($errCode)){ header("location: " . REGPAGE . "?errcode=".$errCode); die; } #FUNC регистрируем пользователя. Файл функции func.php $ret = reg($login , $passw); if ($ret) header("location: ".USERADDEDPAGE); else{ $errCode = 7; header("location: ".REGPAGE."?errcode=".$errCode); } ?> Скрытая часть Код (Text): <?php include("init.php"); include("conf.php"); if(isset($_COOKIE[AUTHSID])){ session_name(AUTHSID); session_start(); $hash = md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']); if ((is_null($_SESSION['userid'])) || ($_SESSION['bind'] != $hash)){ header("location: " . AUTHUSER); die; } } else{ header("location: " . AUTHUSER); die; } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> Вы зашли как зарегистрированный пользователь.<br /> Ваш UID: <?php echo $_SESSION['userid']; ?> <br /><br /><br /> <a href="exit.php">выйти</a> </body> </html> Уф.....Я редкий гость на форумах, поэтому не знаю можно ли выкладывать столько. Написал это за несколько дней. Помогите, кому не сложно.
Для первого раза вполне неплохо. Слишком уж явных ляпов вроде нет. А детальнее, извини, присматриваться не буду - кода достаточно много
init.php не выложил. Там задаем что сессия только куки и , возможно, очистка от слэшей(читал что надо, но не сталкивался)...Может и еще что-нибудь. Подсчет неправильных заходов с одного ип, защита от автоматических регистраций, баны еще добавлю. Данные формы по https и папка со скриптами, которые не будут вызываться непосредственно пользователем в отдельную папку и защита с помощью апача. Пока все, что надумал. Сорри за ошибки- тороплюсь.
Если автор данной темы еще существует хотелосьбы более полный комплект увидить данной авторизации (с недостающими файлами и каждый файл со своим названием) пытался востановить по записям но както все криво вышло
Так как у меня пока не выходит сделать оптимальную авторизацию вечно какие-то "траблы" к примеру в данный момент у меня работает авторизация только в ФФ и Опере а вот в ИЕ (7+) не работает как я уже выяснил сессия не прописывается $_REQUEST['PHPSESSID'] - остается пустым когда пытаюсь залогинеться через ИЕ тоже самое происходит в модуле "Голосования" (привязка попытки повторного голосования к сессии), гость зашедший на сайт через ИЕ и пытающийся проголосовать получает в ответ ошибку о том что он уже голосовал В принципе то что я сейчас использую для авторизации меня устраивает лишь-бы починить интеграцию с ИЕ П.С. в момент авторизации в $_SESSION записывается несколько переменных но после редиректа (или переход на любую другую страницу) $_SESSION становится пустым (в верху сайта на всех страницах фигурирует session_start();)
Invision, он же написал, что программировал на других языках. Если умеешь программировать на других языках, имел опыт работы с базами данных (из того же си, например) - освоить php можно и быстрее. Открыл мануал, нашёл нужную функцию, написал код. Разница-то только в синтаксисе да названиях функций. А алгоритмы составлять уже умеет.