Как сделать авторизацию пользователя на сайте после закрытия браузера?
У меня есть самописный проект на php. При входе если человек решил запомнить себя в системе, то генерируется специальный хеш случайный, который будет записан в бд и в куки, после чего когда закрыл браузер и снова открыл, сессия разрушилась он обращается снова к ресурсу, проверяется есть ли сессия, нету, далее проверяем куки есть ли хеш для авторизации, если есть сверяем его с бд и авторизовываем пользователя в системе, и делаем новую сессию. То есть если будет украдена кука, то можно зайти в личный кабинет юзера, потом подумал может сделать хеш из user-aget + хеш пароль и весь этот хеш записывать в куку, но тут сразу же подумал что и user-aget можно подделать. Вообщем не знаю, что делать. Как авторизовать пользователя на долгое время 2 дня например к личному кабинету более безопасным способом чем кука с хешем пароля и user-aget, как сейчас. Может есть какие-то новые способы.
Используйте TLS (https) и куки с флагом HTTP Only и Secure. В качестве куки лучше использовать достаточно длинный случайный идентфикатор сеанса.
Такую куку нельзя украсть через XSS, можно украсть только получив доступ к браузеру пользователя. Но в случае, если атакующий получил доступ к браузеру, вы уже никак не поможете пользователю. Атакующий будет иметь доступ ко всем, к чему имеет доступ пользователь.
Можно дополнительно привязать куку к автономной системе (AS) и браузеру, но реальной дополнительной защиты это не дает. Привязка к IP ре рекомендуется, т.к. IP может достаточно часто меняться у пользователя, особенно мобильного.
Писать куда-либо хэш пароля не следует, это ничего не дает в плане защиты, но позвоялет сбрутить пароль, если каким-то образом похищена кука (например через баг на поддомене).
Владимир Дубровин А можно попробовать так, что ставим больше время жизни на сессии, затем делаем защиту от кражи (XSS/CSRF атаки) и если браузер не поддерживает работу кук, то пользоваться он им не сможет так ?
+ отключить передачу сессии через get/post запрос.
Владимир Дубровин, В качестве куки лучше использовать достаточно длинный случайный идентфикатор сеанса. Из чего лучше этот идентфикатор сеанса сделать из случайного хеша $hash = md5(rand(0, 6400000));
или есть какой-то более надежный способ ?
Владимир Дубровин,
$bytes = random_bytes(16);
var_dump(bin2hex($bytes));
string(32) "9bfa844f7369219559840b83f2a560e9"
Так норм ?
Какая вероятность создания одинакового хеша в таком случае ?
И этот токен записать в бд, верно понимаю ?
Если в бд, то необходимо чистить их если истек срок, чтобы пользователь не копировал и не вставлял один и тот же токен и был всегда залогинен, тогда понадобиться еще одно поле токен expired, верно ?
Или где-то лучше хранить в другом месте ?
И нужно ли дублировать токен в сессии ?
Дмитрий Тарасов, да, так нормально.
Можно либо хранить в базе/мемкеше либо отдавать клиенту что-то вроде набора токен,uid,срок_действия,подпись_токена и не хранить в базе, а проверять подпись.
Что значит дублировать в сессии?
Если у вас есть сессия и вы хотите привязать аутентификацию к сессии, то никаких токенов не надо, достаточно просто для сессии внутри серверного объекта проставлять флаг что сессия атворизована, тогда фактически сессионная кука станет авторизационной.
Владимир Дубровин, что значит подпись_токена, как можно подписать токен и проверять подпись ?
Дублировать я имел ввиду, токен воткнуть в куки и сессии ?
Какая вероятность создания одинакового токена, таким способом котором я описал выше ?
Дмитрий Тарасов, подписать токен - значит добавить к нему подпись, например sha256(secret, token,uid, datetime). Либо можно зашифровать информацию с помощью серверного ключа и расшифровать при получении.
Я тоже это имел ввиду. Если вы хотите привязать токен к сессии- то зачем он вам вообще нужен?
Вероятность того что два произвольных 16-байтных токена совпадут 2^-128 при правильной реализации, т.е. такая что ей можно пренебречь.