Понимание сценариев использования, преимуществ и недостатков JWT.

Java

После двух предыдущих статей»JSON Web Token — безопасный обмен информацией между веб-приложениями""Восемь мультфильмов, чтобы понять, как использовать JSON Web Token для разработки системы единого входа», я считаю, что все уже должны знать, что такое протокол JWT. по крайней мере увидеть

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxaWFubWlJZCI6InFtMTAzNTNzaEQiLCJpc3MiOiJhcHBfcW0xMDM1M3NoRCIsInBsYXRmb3JtIjoiYXBwIn0.cMNwyDTFVYMLL4e7ts50GFHTvlSJLDpePtHXzu7z9j4

Таким образом, когда используется такая строка, как A.B.C, можно четко распознать, что используется jwt. После размещения этих двух статей многие читатели оставили сообщение в конце статьи, выразив некоторые сомнения относительно того, как используется jwt, и какие сценарии подходят для использования jwt. Я не эксперт в jwt.Как и у многих читателей, у меня были такие же сомнения в начале моего исследования, и еще больше сомнений после постепенного выхода на связь.Обобщение организовано в этой статье.

кодировать, подписывать, шифровать

Эти основы кратко представлены, и не путайте три концепции. В jwt эти три понятия задействованы одновременно.Автор использует просторечие, чтобы сделать популярное объяснение (нестрогое определение, для личного понимания)

Кодировать и декодировать

Как правило, кодирование и декодирование упрощают представление данных в байтах, что удобно для хранения и передачи по сети. Вся строка jwt будет размещена в заголовке http или URL-адресе. Во избежание несчастных случаев, таких как искаженные ошибки синтаксического анализа, необходимо кодирование. в JWT с.Все три разделенные части закодированы в base64 (кодировка секретной части в base64 не является обязательной, а заголовок и полезная нагрузка должны быть закодированы в base64). Обратите внимание, особенность кодирования: весь процесс кодирования и декодирования обратим. Зная метод кодирования, вся строка jwt представляет собой обычный текст. Найдите веб-сайт по желанию, чтобы проверить декодированное содержимое:

base64base64

Так что будьте осторожны,Полезная нагрузка не должна содержать конфиденциальные данные, такие как пароли и другую информацию..

подпись

Цель подписи в первую очередь состоит в том, чтобы убедиться, что я «я». Алгоритм подписи, обычно используемый в jwt, — HS256.Большинство людей могут быть не знакомы с этим алгоритмом подписи, но такие алгоритмы подписи, как md5 и sha, безусловно, хорошо известны.Общая черта алгоритмов подписи заключается в том, что весь процесс необратим. Поскольку основное содержимое (заголовок, полезная нагрузка) перед подписью будет содержаться в строке jwt, необходимо использовать алгоритм подписи с ключом (yuè), а ключ совместно используется сервером и эмитентом. Если часть заголовка и часть полезной нагрузки подделаны, поскольку взломщик не знает, что такое ключ, и не может сгенерировать новую часть подписи, сервер не может ее передать. В jwt тело сообщения прозрачно, а использование подписей может гарантировать, что сообщение не будет изменено.

В статье, перепечатанной ранее, оригинальный автор назвал HS256 алгоритмом шифрования, который не очень строг.

шифрование

Шифрование превращает информацию открытого текста в трудночитаемый зашифрованный контент, что делает его нечитаемым. Только объект с методом расшифровки может восстановить зашифрованный текст до нормального читаемого содержимого посредством процесса расшифровки. Алгоритмы шифрования обычно делятся на симметричное шифрование (например, AES) и асимметричное шифрование (например, RSA) в соответствии с различными методами шифрования. Вы можете задаться вопросом: «Где алгоритм шифрования задействован в jwt?» На самом деле, параметр alg в первой части (заголовке) jwt может указывать разные алгоритмы для генерации третьей части (подписи). Большинство фреймворков, поддерживающих jwt как минимум Все встроенное асимметричное шифрование rsa. Вот и первый вопрос

Вопрос: когда речь заходит о rsa, большинство людей в первую очередь думают об алгоритмах асимметричного шифрования, а четкое английское определение третьей части jwt — подпись, разве это не противоречие?

Фокус!

rsa-шифрованиеиrsa-подписьдва понятия! (Испугался, что мне пришлось переключать линии)

Эти два употребления хорошо понятны:

  • Поскольку оно зашифровано, естественно, я не хочу, чтобы другие знали мое сообщение, расшифровать его могу только я сам, поэтомуОткрытый ключ отвечает за шифрование, а закрытый ключ отвечает за расшифровку.. Это самый распространенный вариант использования rsa для шифрования.
  • Поскольку это подпись, я, естественно, надеюсь, что другие не могут притворяться мной, чтобы отправлять сообщения, только я могу опубликовать подпись, поэтомуЗакрытый ключ отвечает за подпись, а открытый за проверку..

Поэтому, когда клиент использует алгоритм rsa для генерации строки jwt, он использует закрытый ключ для «шифрования», а открытый ключ является открытым, который может быть расшифрован кем угодно, и содержимое не может быть изменено (взломщик не может знать закрытый ключ).

Поэтому в jwt нет чистого процесса шифрования, а шифрование виртуальное, а подпись настоящая.

В каких сценариях следует использовать jwt?

Давайте поговорим о нескольких сценариях. Обратите внимание, что не все следующие сценарии совместимы с jwt.

  1. разовая проверка

Например, пользователю необходимо отправить электронное письмо для активации учетной записи после регистрации.Обычно в письме должна быть ссылка.Эта ссылка должна иметь следующие характеристики: она может идентифицировать пользователя, а ссылка является временной. чувствительный (обычно разрешается активировать только в течение нескольких часов), Его нельзя подделать, чтобы активировать другие возможные учетные записи... Этот сценарий очень близок к характеристикам jwt. Фиксированные параметры в полезной нагрузке jwt: эмитент iss и время истечения срока действия готовы к этому.

  1. Аутентификация без сохранения состояния для спокойного API

Также рекомендуемой схемой использования является использование jwt для спокойной аутентификации API. Клиент и сервер совместно используют секрет; время истечения срока действия проверяется сервером, и клиент регулярно обновляет его; информацию о подписи нельзя изменить... spring security oauth jwt предоставляет полный набор системы аутентификации jwt в соответствии с опыт автора: использовать oauth2 или jwt для аутентификации restful api большой проблемы нет, oauth2 имеет больше функций и поддерживает больше сценариев, а последний легко реализовать.

  1. Используйте jwt для единого входа + управление сеансом (не рекомендуется)

существует"Восемь мультфильмов, чтобы понять, как использовать JSON Web Token для разработки системы единого входа«В статье упоминалось использование jwt для выполнения единого входа, и остальная часть этой статьи посвящена обсуждению этого вопроса. Если вы планируете использовать jwt+cookie вместо session+cookie, я настоятельно не рекомендую этого делать.

Прежде всего, давайте проясним: использование jwt для разработки системы единого входа — менее строгое утверждение. Во-первых, предпосылкой схемы cookie+jwt является не междоменный единый вход (куки-файлы не могут быть автоматически перенесены на другие доменные имена), а во-вторых, система единого входа содержит множество технических деталей, по крайней мере, включая аутентификацию личности и управление сеансом, что не включает управление полномочиями. Если вы думаете, что это абстрактно, вы можете также использовать традиционную схему единого входа сеанс + файл cookie в качестве аналогии.Обычно мы можем выбрать Spring Security (инфраструктура безопасности для аутентификации и управления полномочиями) и Spring Session (совместное использование сеанса). построить и выбрать использование Дизайн JWT системы единого входа должен решить множество проблем, которые также существуют и не существуют в традиционных решениях, которые подробно перечислены ниже.

Что делать, если токен jwt просочился?

Многие комментировали эту проблему в предыдущей статье, но я не думаю, что это проблема. В традиционной схеме сеанс + файл cookie, если происходит утечка идентификатора сеанса, другие также могут украсть вашу личность. Лучше суп поднять, чтобы он перестал кипеть, чем тянуть зарплату со дна котелка Давайте проследим источник, какой сценарий приведет к утечке вашего jwt.

Следуйте следующим рекомендациям, чтобы максимально защитить ваш jwt от утечки: используйте https для шифрования вашего приложения, установите httpOnly=true при возврате jwt клиенту и используйте cookie вместо LocalStorage для хранения jwt, что может предотвратить атаки XSS и CSRF. атаки (Детская обувь, которая заинтересована в этих двух атаках, может увидеть их введение в весенней безопасностиCSRF, XSS)

Если вы используете jwt для доступа к интерфейсу, в это время ваш коллега подбежит и скопирует ваш jwt.Такая утечка бессильна.

Как разработать секрет

Единственное, что jwt хранит на сервере — это секрет, Лично я считаю, что этот секрет должен быть связан с пользователем, а не унифицированным значением, общим для всех пользователей. Это может эффективно избежать некоторых дилемм, возникающих при выходе из системы и смене паролей.

Выйти и изменить пароль

В традиционной схеме сеанс + файл cookie пользователь щелкает, чтобы выйти из системы, и сервер очищает сеанс, поскольку состояние сохраняется на сервере. Но решение с jwt более сложное, потому что jwt не имеет состояния, а сервер проверяет правильность вычислением. Он не сохраняется, поэтому, даже если клиент удалит jwt, jwt все еще действителен, но в свободном состоянии. Проанализируйте болевую точку: причина, по которой выход из системы усложняется, заключается в том, что jwt не имеет состояния. Я предлагаю несколько вариантов, в зависимости от конкретного бизнеса, чтобы решить, приемлемо это или нет.

  • Просто очистите куки клиента, чтобы пользователь не нес jwt при доступе, а сервер думал, что пользователю нужно авторизоваться заново. Это типичный поддельный выход из системы. Пользователи, которые демонстрируют поведение выхода, на самом деле в это время все еще могут получить доступ к системе с соответствующим jwt.
  • Очистите или измените секрет, соответствующий пользователю на стороне сервера, чтобы после выхода пользователя из системы сам jwt оставался неизменным, но поскольку секрет не существует или изменяется, проверка не может быть завершена. Вот почему секреты разработаны так, чтобы быть актуальными для пользователя.
  • С помощью стороннего хранилища для управления состоянием jwt вы можете использовать jwt в качестве ключа для проверки существования промежуточного программного обеспечения кэширования, такого как Redis. Дизайн схемы не сложен, но после введения redis jwt без сохранения состояния стал с состоянием, что нарушает первоначальный замысел jwt. По сути, эта схема почти аналогична сессии.

Смена пароля немного отличается.Предполагая, что номер был получен, после смены пароля (это пароль пользователя, а не секрет jwt) хакер все еще может продолжать доступ к системе в течение срока действия исходного jwt, поэтому недостаточно просто очистить куки, что требует обязательной модификации секрета. Вот как это делается в моей практике.

Проблемы с продлением

Проблема обновления, возможно, является основной причиной, по которой я отказываюсь использовать jwt для замены традиционных сеансов, потому что в дизайне jwt я не обнаружил, что он рассматривает обновление как собственную функцию. Обычно в фреймворк встроена традиционная схема обновления куки: сессия действительна 30 минут, при посещении в течение 30 минут период действия сессии обновляется до 30 минут. В самой полезной нагрузке jwt также есть параметр времени истечения срока действия, чтобы представить своевременность jwt, и jwt хочет отложить это выражение, потому что полезная нагрузка участвует в подписи. Строка jwt изменилась, и фича jwt естественно не поддерживает обновление!

Если вы должны использовать jwt для управления сеансом (сохранение информации о сеансе в полезной нагрузке), это не без решений, но я лично думаю, что это не очень удовлетворительно.

  1. обновлять jwt при каждом запросе

После того, как jwt изменит exp в полезной нагрузке, изменится вся строка jwt, так что... пусть она станет лучше, и возвращайте клиенту новый jwt для каждого запроса. Слишком грубая сила, мне не нужно вдаваться в подробности о том, насколько это неэлегантно и какие проблемы с производительностью это приносит.

Но, по крайней мере, это самое простое решение.

  1. Просто обновите jwt, когда срок его действия истечет.

Модификация приведенной выше схемы заключается в возврате клиенту нового jwt только за последние несколько минут. Таким образом, запуск jwt обновления в основном зависит от удачи.Если пользователь получает доступ к серверу в последние несколько минут и запускает обновление, все будет в порядке; если пользователь работает непрерывно в течение 27 минут, только последние 3 минуты не имеют операции, что приводит к тому, что jwt не обновляется. , несомненно, сведет пользователей с ума.

  1. Улучшить маркер обновления

Основываясь на дизайне oauth2, RefreshToken возвращается клиенту, позволяя клиенту активно обновлять файл jwt. Как правило, время истечения срока действия jwt может быть установлено в часах, а время истечения срока действия refreshToken — в днях.

Я думаю, что это решение осуществимо, но для решения проблемы обновления jwt весь процесс был изменен, почему бы не рассмотреть режим пароля и режим клиента oauth2?

  1. Используйте Redis для записи независимого времени истечения срока действия

На самом деле, из-за исторических проблем в моем проекте, jwt используется для входа в систему и управления сеансом.Чтобы решить проблему обновления, мы устанавливаем время истечения каждого jwt в redis отдельно и обновляем время истечения jwt каждый раз, когда мы visit , если jwt не существует в Redis, он считается просроченным.

Советы: точно контролировать время истечения срока действия redis — непростая задача.Вы можете обратиться к моей недавней статье, объясняющей время истечения срока действия redis с помощью весенней сессии.

Это также изменило процесс jwt, но что ж, мир безопасен и надежен. Я могу только посоветовать вам, друзья, которые еще не использовали jwt для управления сессиями, попробуйте использовать традиционное решение session+cookie, существует множество зрелых фреймворков распределенных сессий и фреймворков безопасности, которые вы можете использовать из коробки.

JWT, OAUTH2, сессия 千 万

Конкретное сравнение в этой статье не приводится, я отвечу на его вопрос, исходя из сообщения читателя.

С такой длинной строкой я мог бы также хранить данные в базе данных и сопоставлять их с длинным ключом, с которым трудно столкнуться, то есть с выделенным токеном.

Этот брат считает, что jwt слишком длинный, можете ли вы использовать тот же uuid, что и oauth2, для сопоставления. Здесь, естественно, есть проблема: JWT не только используется для аутентификации личности (проверяет правильность подписи, существует ли эмитент, истек ли ограниченный период), но и хранит информацию о сеансе в своей полезной нагрузке, что является самым большим отличием. между jwt и сеансом.Разница в том, что один несет информацию о сеансе на стороне клиента, а другой хранит информацию о сеансе на стороне сервера. Если вы действительно хотите поместить информацию jwt в общее хранилище, то больше нет смысла использовать jwt.

И jwt, и oauth2 могут использоваться для спокойной аутентификации.Из моего личного опыта, Spring Security oauth2 может очень хорошо использовать различные режимы аутентификации: режим клиента, режим пароля, неявный режим (режим кода авторизации - это не простой интерфейс, режим аутентификации), он также может легко реализовать контроль разрешений, какой API нуждается в каких полномочиях, какой ресурс нуждается в какой области... и jwt я использовал его только для аутентификации личности, функция относительно проста (может быть, это больше применения не нашел).

Суммировать

В веб-приложениях использование jwt вместо session — это не малый риск, приходится решать как минимум те проблемы, о которых говорилось в этой статье, в большинстве случаев традиционный механизм cookie-session работает лучше. jwt подходит для простой спокойной аутентификации API, выдачи jwt с фиксированным сроком действия, снижения риска раскрытия jwt и отсутствия управления состоянием на стороне сервера для jwt, чтобы отразить преимущества jwt без сохранения состояния.

Может быть некоторые места, которые должны быть не восприниматься мной, следят за исходным кодом Spring Security Oauth Jwt, и новые открытия не будут найдены.