жизненный опыт:
Разница между аутентификацией и авторизацией:
Аутентификация: аутентификация пользователя, которая относится к проверке личности пользователя. Например, если вы хотите войти в систему как Сяо А, тогда приложение должно подтвердить, что вы действительно Сяо А, с помощью имени пользователя и пароля.
Авторизация: авторизация означает предоставление вам разрешений после подтверждения вашей личности.Например, пользователь А может изменять данные, а пользователь Б может только читать данные.
Поскольку протокол http не имеет состояния, каждый запрос не имеет состояния. Когда пользователь входит в систему с именем пользователя и паролем, его следующий запрос не будет содержать никакого состояния, приложение не может узнать его личность, оно должно пройти повторную аутентификацию. Поэтому мы надеемся, что статус входа пользователя можно будет сохранять для каждого http-запроса после успешного входа пользователя.
Текущие основные методы аутентификации пользователей основаны на токенах и сеансах.
Аутентификация пользователя на основе сеанса
Процесс аутентификации на основе сеанса выглядит следующим образом:
-
Пользователь вводит данные для входа
-
Сервер проверяет правильность информации и создает сеанс, который затем сохраняется в базе данных.
-
Сервер генерирует идентификатор сеанса для пользователя, и файл cookie с идентификатором сеанса будет помещен в браузер пользователя.
-
В последующих запросах идентификатор сеанса будет сверяться с базой данных, и, если он действителен, запрос будет принят.
-
Как только пользователь выйдет из приложения, сеанс будет уничтожен как на стороне клиента, так и на стороне сервера.
Аутентификация пользователя на основе токенов
Наиболее часто используется JSON Web Token (jwt):
-
Пользователь вводит данные для входа
-
Сервер проверяет правильность информации и возвращает подписанный токен.
-
Токен хранится на стороне клиента, например, в локальном хранилище или в файле cookie.
-
Последующие HTTP-запросы будут добавлять токен в заголовок запроса.
-
Сервер декодирует JWT и принимает запрос, если токен действителен.
-
Как только пользователь выйдет из системы, токен будет уничтожен на стороне клиента, никакого взаимодействия с сервером не требуется.Одним из ключевых моментов является то, что токен не имеет состояния. Внутреннему серверу не нужно вести запись токена или текущего сеанса.
Состав jwt
Принцип аутентификации jwt:
На самом деле jwt — это строка, состоящая из трех частей: заголовка, полезной нагрузки и подписи, все в формате json.
Заголовок
Заголовок используется для описания самой основной информации о JWT, такой как его тип и алгоритм, используемый для его подписи.
{
"typ": "JWT",
"alg": "HS256"
}
Здесь мы заявляем, что это JWT и что используемый нами алгоритм подписи — это алгоритм HS256.
Полезная нагрузка
Полезная нагрузка может использоваться для размещения неконфиденциальной информации.
{
"iss": "John Wu JWT",
"iat": 1441593502,
"exp": 1441594722,
"aud": "www.example.com",
"sub": "jrocket@example.com",
"from_user": "B",
"target_user": "A"
}
Первые пять полей здесь определены стандартом JWT.
- iss: эмитент этого JWT
- sub: пользователь, для которого предназначен этот JWT
- aud: сторона, получившая JWT
- exp(expires): когда истекает, вот временная метка Unix
- iat(выпущено в): когда он был выпущен После кодирования Base64 заголовка и полезной нагрузки соответственно получаются две строки, а затем две закодированные строки соединяются вместе с английскими точками (заголовок идет первым), чтобы сформировать новую строку:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0
подпись
Наконец, мы шифруем объединенную выше строку с помощью алгоритма HS256. При шифровании нам также необходимо предоставить секрет. Зашифрованное содержимое также является строкой, а последняя строка является подписью, и полный jwt можно получить, вставив эту подпись за предыдущей строкой. Если часть заголовка и часть полезной нагрузки подделаны, потому что взломщик не знает, что такое ключ, и не может сгенерировать новую часть подписи, сервер не может пройти.В jwt тело сообщения прозрачно, и использование подписей может гарантировать, что сообщение не подделано.
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
Отличия и преимущества и недостатки:
Основное различие между методами, основанными на сеансе, и методами, основанными на jwt, заключается в том, где сохраняется состояние пользователя: сеанс сохраняется на стороне сервера, а jwt — на стороне клиента.
Преимущества jwt:
-
Хорошая масштабируемость Когда приложение развернуто распределенным образом, сеанс необходимо разделить между несколькими машинами, которые обычно можно хранить в базе данных или Redis. И JWT не нужен.
-
нет статуса jwt не хранит никакого состояния на сервере. Один из принципов RESTful API заключается в том, что он не имеет состояния, при выполнении запроса всегда возвращается ответ с параметрами без каких-либо дополнительных воздействий. Состояние аутентификации пользователя вводит этот дополнительный эффект, который нарушает этот принцип. Кроме того, в полезной нагрузке jwt может храниться некоторая общая информация для обмена информацией.Эффективное использование JWT может сократить количество запросов сервера к базе данных.
Недостатки jwt:
- безопасность
Поскольку полезная нагрузка jwt закодирована с использованием base64 и не зашифрована, конфиденциальные данные не могут храниться в jwt. Информация о сеансе хранится на стороне сервера, что относительно безопаснее.
- представление
jwt слишком длинный. Поскольку JWT используется без сохранения состояния, все данные помещаются в JWT. Если требуется какой-то обмен данными, нагрузка будет больше. После кодирования JWT будет очень длинным. Предельный размер файлов cookie обычно составляет 4 КБ, и файлы cookie, скорее всего, быть Не могу оторваться, поэтому jwt обычно помещается в локальное хранилище. И каждый http-запрос пользователя в системе будет содержать jwt в заголовке, а заголовок http-запроса может быть больше, чем тело. И sessionId — это просто очень короткая строка, поэтому HTTP-запрос с использованием jwt намного дороже, чем использование сеанса.
- Одноразовый
Безгражданство — это особенность jwt, но она же и вызывает эту проблему, jwt одноразовая. Если вы хотите изменить содержимое внутри, вы должны создать новый файл jwt.
(1) Нельзя выбрасывать Из приведенного выше механизма проверки jwt видно, что после выдачи jwt он всегда будет действительным, пока не истечет срок его действия, и от него нельзя отказаться на полпути. Например, если вы храните некоторую информацию в полезной нагрузке, когда информацию необходимо обновить, вы повторно выпустите jwt, но, поскольку срок действия старого jwt еще не истек, вы все равно можете войти в систему со старым jwt. , сервер получит jwt от jwt Полученная информация устарела. Чтобы решить эту проблему, нам нужно развернуть дополнительную логику на сервере, например, установить черный список.После выпуска нового jwt старый будет добавлен в черный список (например, сохраненный в Redis), чтобы избежать использования снова.
(2) Продление Если вы используете jwt для управления сессией, в фреймворк обычно встроена традиционная схема обновления куки: сессия действительна в течение 30 минут. Если в течение 30 минут есть посещение, срок действия обновляется до 30 минут. Точно так же, чтобы изменить действительное время jwt, необходимо выпустить новый jwt. Самый простой способ — обновлять jwt при каждом запросе, то есть каждый http-запрос возвращает новый jwt. Этот метод не только жестокий и неэлегантный, но также требует jwt-шифрования и дешифрования для каждого запроса, что приведет к проблемам с производительностью. Другой метод — установить время истечения срока действия для каждого jwt отдельно в Redis и обновлять время истечения срока действия jwt при каждом доступе к нему.
Видно, что если вы хотите взломать одноразовую фичу jwt, вам нужно хранить состояние jwt на сервере. Но после введения redis jwt без сохранения состояния стал с состоянием, что нарушило первоначальный замысел jwt. И эта программа и сессия почти одинаковы.
Суммировать
Сценарии, подходящие для использования jwt:
- Короткий срок действия
- хочу использовать только один раз
Например, когда пользователь отправляет электронное письмо для активации своей учетной записи после регистрации, обычно в электронном письме содержится ссылка. Эта ссылка должна иметь следующие характеристики: она может идентифицировать пользователя, и ссылка чувствительна ко времени (обычно только разрешено активировать в течение нескольких часов), нельзя вмешиваться для активации других возможных учетных записей, однократно. Этот сценарий подходит для использования jwt.
И потому, что у jwt есть одноразовая функция. Единый вход и управление сеансом очень не подходят для jwt.Если на сервере развернута дополнительная логика для хранения состояния jwt, лучше использовать сеанс. Существует множество зрелых фреймворков, основанных на сеансе, которые можно использовать «из коробки», но с jwt вам придется реализовывать логику самостоятельно.