Пишу, вернее, модернизирую систему управления юзерами для сайта небольшого интернет-магазина. В процессе работы над алгоритмом возникли четыре вопроса:
1. Есть ли смысл при регистрации нового юзера посылать ему письмо, заставляя активировать аккаунт, пройдя по некой ссылке, или лучше обойтись без этого?
2. Допустим, юзер зарегистрирован. Имеет ли смысл в форме входа, кроме логина и пароля, предусмотреть чекбокс «Запомнить меня», или запоминать всех по умолчанию, сводя к минимуму разные вопросы?
3. При успешной авторизации я пишу в сессию логин и двойной хэш пароля из базы (в базе, само собой, хранится двойной хэш пароля), а также пишу в куку некий token для автологина: $token = md5(time().$username);
setcookie('token', $token, time ( ) + 2592000, "/");
$res = $db->query("UPDATE users SET token = '".$token."' WHERE username = '".$username."'");
Разные учебные пособия, сайты и форумы по-разному решают эту задачу. В чем минусы моего решения? Имеет ли смыл добавлять «соль», например к хэшу пароля или в token: define('MY_SALT', 'KEJ2FHE#WJFHW758');
4. При обращении к каждой страницы сайта я проверяю, есть ли данные сессии, а потом у меня идет обязательный запрос к базе данных, примерно такой: if ( isset ( $_SESSION["username"] ) && isset ( $_SESSION["userpass"] ) ) {
$db->query("SELECT * FROM users
WHERE username = '".$_SESSION["username"]."'
AND userpass = '".$_SESSION["userpass"]."'
.....}
Но некоторые пособия и учебники делают просто: если есть данные сессии, показывают страницу, если нет — не пускают, при этом запроса к базе данных нет, например: if(isset($_SESSION['user_data']))
$message[] = "Приветствуем Вас, ". htmlspecialchars($_SESSION['user_data']['login']) ."! Рады видеть Вас на сайте";.........................
1. Только в том случае, если вам необходим этот адрес для его дальнейшего использования, потому как валидация в интернет-магазинах у нас, как правило, происходит по телефонному звонку — что позволяет удостовериться в наличии пользователя и заказа (почти 100%). По сути, адрес можно подтвердить и уже после работы с интернет-магазином и за это в ответ дать сладких плюшек каких-нибудь, а потом присылать рассылки с новыми поступления по направлениям которые ему интересны.
2. Есть смысл чекбокса по дефолту включенного, но если человек не захочет — он просто снимет галочку. Многие не продвинутые пользователи сейчас об этом не задумываются, приняв по дефолту то, что сайт их запоминает. А ещё рекомендую пробежаться по популярным сервисам типа однокласснки, вконтакт и т.п. и посмотеть как у них и не отсупать от этого — схожесть в визуальном плане и поведении стандартных наборов элементов управления является одним из озносных параметров дружественного интерфейса.
3. Рекомендовал бы привязаться не только к имени пользователя (или вобще НЕ к нему), а к данным браузера — имя пользователя то у сессии всегда одно и то же, а вот если к данным браузера привязаться, то утащив куки с сессией злодею надо будет подтасовывать и все идентификационные данные браузера.
4. По идее сессия и нужна для того, чтобы не лазить каждый раз за проверкой. Сейчас у вас бессмыслица — зачем проверять тот ли логин с паролем в базе из сессии, если в сессию вы сами их и положили? Каким образом они могут отличаться? Пользователю недоступно изменение данных сессии, это делает ваш скрипт.
Именно такого 4-го пункта я и ждал. Я уж думал что совсем все «привет» :) все верно. С 3-м пока не заморачивался, не такие важные сайты, но там есть простор для фантазии
всё что ниже — субъективно
1. для интернет магазина это лишнее. самое то использовать три варианта: заказ без регистрации, регистрация через openid, обычная регистрация.
2. имеет, это очень удобно. только title на чекбокс сделайте с коротким объеснением зачем это.
3. соль нужна для того что бы «усугубить» хеш, а самое главное для того что бы в базе был один хеш (а рядом соль) а в сессию писать уже с солью.
4. я обычно «гостю» ставлю в куку id=1 и пароль md5(rand()), а на страницах уже проверяю, если значение id больше 1 то делаю идентификацию, если 1 то нет.
1. Без активации мыла на первый взгляд проще и удобнее. Но думаю юзеру будет неприятно узнать, что он сделал опечатку в поле email, когда нужно будет восстановить пароль к учетке. Хотя тут тоже зависит от назначения вашего сервиса, может привязка к мылу как таковая особо и не нужна.
3. Используете свой велосипед? Зачем?
4. >проверяю, есть ли данные сессии, а потом у меня идет обязательный запрос к базе данных
вот из такого и вырастают чудо-скрипты, ставящие раком любой сервер. Тут запросик, там запросик. Не ленитесь, делайте по-человечески сразу, к тому же это и удобнее.
Спасибо! К сожалению, в вашем ответе прозвучало «по-человечески», однако совершенно нет никакого рецепта, даже намека. Повторюсь, мой вопрос назрел после изучения нескольких пособий, руководств, форумов. Каждый ратует за свой метод. Хочу разобраться как сделать правильнее.
Пробуйте любой форум не почитать, а исходники посмотреть и структуру БД. странное решение для руководства по программированию каждый раз брать из сессии и проверять на правильность имя пользователя и пароль — это совершенно лишний запрос. Короче горе-писатели не перевелись еще, теперь они еще и руководства пишут.
Не знаю что тут вам про sql-injection понаписали, по-идее массив $_SESSION подменить со стороны клиента нельзя, хотя лучше сразу привыкать все делать нормально типа mysql_real_escape_string($_SESSION['user_data']).
>однако совершенно нет никакого рецепта, даже намека.
есть официальная документация и здравый смысл. Достаточно разобраться, как работает механизм сессий и для чего он собственно предназначен. А одно из главных предназначений — снизить нагрузку на БД.
Что касается безопасности, то тут вполне достаточно не передавать ключи в урле. Дополнительно можно привязывать куки к конкретному браузеру и системе. Ну и в критичных местах все это еще в SSL заворачивается, если есть резон.
И все-таки, зачем вы пишите свою реализацию сессий?
непонятно зачем вообще нужны пункты 3 и 4.
я бы еще понял, если бы токен был одноразовый, а так вы просто повторяете существующий механизм сессии, навешивая на него какие-то лишние навороты.
храните в сессии user_id и какой-то флаг is_logged и очищайте сессию при отлогине.