Безопасный метод авторизации на PHP Примечание: мини-статья написана для новичков Давайте посмотрим вокруг: форумы, интернет магазины, гостевые книги и т.д. используют регистрацию и последующую авторизацию пользователей. Можно даже сказать, что это почти необходимая функция каждого сайта (только если это не домашняя страничка Васи Пупкина или не визитная карточка, какой-нибудь небольшой компании). Сегодня я хочу поделиться со всеми новичками информацией, о том, как лучше это все реализовать. 1. Модель (клиент) Регистрация - логин (a-z0-9) - пароль Вход - логин - пароль Cookie - уникальный идентификатор юзера - хэш Модель (сервер) MySQL Таблица users user_id (int(11)) user_login (Varchar(30)) user_password (varchar(32)) user_hash (varchar(32)) user_ip (int(10)) по умолчанию 0 При регистрации в базу данных записываеться логин пользователя и пароль(в двойном md5 шифровании) При авторизация, сравниваеться логин и пароль, если они верны, то генерируеться случайная строка, которая хешируеться и добавляеться в БД в строку user_hash. Также записываеться IP адрес пользователя(но это у нас будет опциональным, так как кто-то сидит через Proxy, а у кого-то IP динамический... тут уже пользователь сам будет выбирать безопасность или удобство). В куки пользователя мы записываем его уникальный индетификатор и сгенерированный hash. Почему надо хранить в куках хеш случайно сгенерированной строки, а не хеш пароля? 1. Из-за невнимательности программиста, во всей системе могут быть дырки, воспользовавшийсь этими дырками, злоумышленик может вытащить хеш пароля из БД и подставить его в свои куки, тем самым получить доступ к закрытым данным. В нашем же случае, двойной хеш пароля не чем не сможет помочь хакеру, так как расшифровать он его не сможет(теоретически это возможно, но на это он потратит не один месяц, а может быть и год) а воспользоваться этим хешем ему негде, ведь у нас при авторизации свой уникальный хеш прикрепленный к IP пользователя. 2. Если злоумышленик вытащит трояном у пользователя уникальный хеш, воспользовать им он также не сможет(разве если только, пользователь решил принебречь своей безопастностью и выключил привязку к IP при авторизации). 2. Практика -- — Структура таблицы `users` — CREATE TABLE `users` ( `user_id` int(11) unsigned NOT NULL auto_increment, `user_login` varchar(30) NOT NULL, `user_password` varchar(32) NOT NULL, `user_hash` varchar(32) NOT NULL, `user_ip` int(10) unsigned NOT NULL default '0', PRIMARY KEY (`user_id`) ) ENGINE=MyISAM DEFAULT CHARSET=cp1251 AUTO_INCREMENT=1 ; register.php 30) { $err[] = "Логин должен быть не меньше 3-х символов и не больше 30"; } # проверяем, не сущестует ли пользователя с таким именем $query = mysql_query("SELECT COUNT(user_id) FROM users WHERE user_login='".mysql_real_escape_string($_POST['login'])."'"); if(mysql_result($query, 0) > 0) { $err[] = "Пользователь с таким логином уже существует в базе данных"; } # Если нет ошибок, то добавляем в БД нового пользователя if(count($err) == 0) { $login = $_POST['login']; # Убераем лишние пробелы и делаем двойное шифрование $password = md5(md5(trim($_POST['password']))); mysql_query("INSERT INTO users SET user_login='".$login."', user_password='".$password."'"); header("Location: login.php"); exit(); } else { print "При регистрации произошли следующие ошибки:
"; foreach($err AS $error) { print $error."
"; } } } ?>
Логин
Пароль
login.php
Логин
Пароль
Не прикреплять к IP(не безопасно)
check.php Для защиты формы логина от перебора, можно использовать капчу. Хочу отметить, что здесь я рассматривал авторизацию основоную на cookies, не стоит в комментариях кричать, что сессии лучше/удобнее и т.д. Спасибо.