Как правильно реализовать систему блокировки пользователя?
Здравствуйте. В своем приложении реализую систему авторизации. После нескольких неудачных попыток входа, пользователь должен быть заблокирован и разблокирован после нескольких часов.
Как сделал это я:
есть таблица пользователей, в которой есть идентификатор, логин, хеш от пароля, соль и другая служебная информация.
Есть таблица, в которую добавляются все неудачные попытки входа. Она имеет следующую структуру: идентификатор пользователя (Внешний ключ на идентификатор в таблице с пользователями), IP, количество неудачных попыток.
Также в этой таблице есть триггер, который срабатывает при вставке и обновлении. Если попыток входа > 5, то пользователь добавляется в таблицу, где находятся все заблокированные пользователи. Эта таблица имеет следующую структуру: идентификатор пользователя (Внешний ключ на таблицу с пользователя), время блокировки (Когда пользователь был заблокирован), время разблокировки (Когда пользователя надо разблокировать).
Есть процедура, которая запускается с помощью планировщика и разблокирует пользователей, у которых время разблокировки пришло.
Что можете сказать насчёт моего решения?
П.С. Используется база данных Postgresql.
Да, решение работает, но хотелось бы сделать так, как делать надо, а не что-нибудь, что лишь бы работало.
Ваше решение работает.
Алгоритм реализованный вами не только выполняет функцию блокировки но и формирует статистику - что уже больше самой задачи.
Если рассуждать "как правильно" - ИМХО серебряной пули нет.
Кстати, ваш вариант имеет "задел на будущее".
Если блок проверки основания для блокировки (расчет сколько) вынести в отдельную функцию, а в триггере ее вызывать, это позволить реализовать другие алгоритмы блокировки (функции принятия решения) и дополнительно (или вместо) вызывать их в триггере. Можно даже реализовать целую систему из таких компонентов...
Вот только я думаю Система авторизации и блокировки не весь функционал вашей системы - и есть ли смысл для одной операции строить целую систему?
>> я заблокирую мирных пользователей
> это лучше, чем если вы подберёте пароли
т.е., защищаясь от одной уязвимости, вы внедряете другую, причём такую, которую использовать в разы проще?
Василий Назаров, я думал да, базу данных можно положить, но если будут прям реально атаковать, то после блокировки на уровне базы данных, можно заблокировать на уровне firewall.
Можно обойтись одной таблицей с неудачными попытками. Структура:
ID пользователя
IP адрес
Дата/время
При авторизации делаете запрос за x последние x часов, если неудачных попыток больше y, вычисляете, до какого времени пользователь должен быть заблокирован. Если это время еще не прошло, не пускаете пользователя. Все это можно вычислить в запросе.
Обновлять дополнительно ничего не нужно. Периодически можно чистить таблицу.