Всё неправильно. Восстановление пароля делается так:
0) с формы запроса восстановления ловите данные, по которым будете восстанавливать. Капча или чего-нибудь другое, чтобы не беспокоить пользователя зря от активности ботов. Ищете в СУБД, что такое у вас реально есть.
1) дёргаете random_bytes желаемой длины. Например, 16 байт криптографического мусора вполне достаточно при сохранении урла вменяемой длины. Для старых версий PHP
2) сохраняете полученный токен в какое-нибудь временное хранилище с соответствием user_id и датой генерации токена. редис, мемкеш, можно и в РСУБД.
3) на почту отправляете ссылку с этом токеном. base64, base_convert, или тупой binhex для нормальной передачи бинарного токена.
4) ловите переход с этим токеном. Ищете токен среди выданных ранее, проверяете дату его генерации. Допустимый лимит жизни токена обязан быть ограничен небольшой величиной, например в полчаса-час.
Токена нет/протух - отлуп.
5) токен в норме - даёте форму смены пароля. В hidden-поле передаёте этот же токен, либо генерируете новый на сессию.
6) получение формы смены пароля: проверяете токен с сессионным через timing-safe функцию hash_equals. Если ок, и токен ещё не протух - меняете пароль в базе на новый, авторизуете пользователя, логируете смену пароля через восстановление, удаляете или архивируете выданный токен. Токен обязан быть одноразовым.
Сверху помазать каким-нибудь разумным ограничением на количество запросов в единицу времени для затруднения попыток брутфорса.
|