Обычно разделяют сессии и авторизацию:
Сессия. Чтобы реализовать сессии сервер при первом соединении с клиентом может генерировать некоторый случайный токен и устанавливать его в куки. Тут важно, что куки должны передаваться по защищённому каналу (HTTPS). Таким образом можно сохранять некоторую информацию о сессии в базе данных или же в самих куки, но тогда нужно подписывать куки, чтобы пользователь не мог их изменять.
В любом случае, сервер будет хранить информацию о активных сессиях в БД.
Подписать куки можно, например, добавив в них помимо нужной вам информации какой-нибудь
HMAC.
Авторизация. Сервер никогда не хранит пароли. В базе данных хранят логин и хеш пароля (на самом деле нет). Для авторизации пользовтель передаёт логин и пароль (HTTPS). Сервер вычисляет хеш от пароля и, если он совпадает, сессия помечается как авторизованная.
Соль. Теперь представим, что вы действительно храните логин и хеш пароля в таблице:
login | pass_hash
------+----------
vasya | 4B32E1C...
В идеальном мире это бы неплохо работало. Но в реальном мире 90% ваших пользователей будут иметь пароль вида 12345, password, password123, etc. Соответственно в базе данных будет много одинаковых хешей и злоумышленнику не составит труда быстро подобрать пароли большинства ваших пользователей.
Для этого для каждого пользователя сервер сохраняет некоторые уникальные случайные данные (соль). А вместо хеша пароля хранится
hash(pass + salt)
.
login | salt | hash
------+--------+-----
vasya | 4B3... | 2A3B9...
Таким образом усложняется перебор паролей по словарю.
Хеш. Возможно вы где-то видели или слышали про MD5. Так вот, MD5 на сегодняшний день
не является надёжной криптографической хеш функцией и даже если вы примените MD5 сто или тысячу раз, это не сильно изменит ситуацию. На сегодняшний день
рекомендуется использовать SHA-2 или SHA-3.
P. S. Соль и токены
обязательно должны быть сгенерированы с помощью
CSPRNG.