JJWT стремится стать самой простой в использовании и понимании библиотекой для создания и проверки веб-токенов JSON (JWT) и веб-ключей JSON (JWK) на JVM и Android.
JJWT — это чистая реализация Java, основанная исключительно на спецификациях RFC рабочей группы JOSE:
RFC 7519: веб-токен JSON (JWT).
RFC 7515: веб-подпись JSON (JWS)
RFC 7516: Веб-шифрование JSON (JWE)
RFC 7517: Веб-ключ JSON (JWK)
RFC 7518: Веб-алгоритмы JSON (JWA)
RFC 7638: Отпечаток веб-ключа JSON
RFC 9278: URI отпечатка веб-ключа JSON
RFC 7797: опция незакодированной полезной нагрузки JWS
RFC 8037: алгоритмы кривой Эдвардса и JWK
Он был создан Лесом Хэзлвудом и поддерживается сообществом участников.
JJWT имеет открытый исходный код в соответствии с условиями лицензии Apache 2.0.
PublicKey
JWKtoString()
БезопасностьПолнофункционален на всех Java 7+ JDK и Android.
Рекомендации и утверждения по автоматической безопасности
Простой в освоении и чтении API
Удобные и читаемые интерфейсы, отлично подходят для автодополнения IDE для быстрого написания кода.
Полностью соответствует спецификации RFC по всем реализованным функциям, проверено на соответствие тестовым векторам, указанным в RFC.
Стабильная реализация с почти 1700 тестами и гарантированным 100% покрытием тестового кода. Каждый отдельный метод, оператор и вариант условного перехода во всей базе кода тестируется и требуется для каждой сборки.
Создание, анализ и проверка компактных JWT с цифровой подписью (также известных как JWS) со всеми стандартными алгоритмами JWS:
Идентификатор | Алгоритм подписи |
---|---|
| HMAC с использованием SHA-256 |
| HMAC с использованием SHA-384 |
| HMAC с использованием SHA-512 |
| ECDSA с использованием P-256 и SHA-256 |
| ECDSA с использованием P-384 и SHA-384 |
| ECDSA с использованием P-521 и SHA-512 |
| RSASSA-PKCS-v1_5 с использованием SHA-256 |
| RSASSA-PKCS-v1_5 с использованием SHA-384 |
| RSASSA-PKCS-v1_5 с использованием SHA-512 |
| RSASSA-PSS с использованием SHA-256 и MGF1 с SHA-256 1 |
| RSASSA-PSS с использованием SHA-384 и MGF1 с SHA-384 1 |
| RSASSA-PSS с использованием SHA-512 и MGF1 с SHA-512 1 |
| Алгоритм цифровой подписи на основе кривой Эдвардса 2 |
1. Требуется Java 11 или совместимый поставщик JCA (например, BouncyCastle) в пути к классам среды выполнения.
2 . Требуется Java 15 или совместимый поставщик JCA (например, BouncyCastle) в пути к классам среды выполнения.
Создание, анализ и расшифровка зашифрованных компактных JWT (также известных как JWE) с использованием всех стандартных алгоритмов шифрования JWE:
Идентификатор | Алгоритм шифрования |
---|---|
| Алгоритм шифрования с проверкой подлинности AES_128_CBC_HMAC_SHA_256 |
| Алгоритм шифрования с проверкой подлинности AES_192_CBC_HMAC_SHA_384 |
| Алгоритм шифрования с проверкой подлинности AES_256_CBC_HMAC_SHA_512 |
| AES GCM с использованием 128-битного ключа 1 |
| AES GCM с использованием 192-битного ключа 1 |
| AES GCM с использованием 256-битного ключа 1 |
1 . Требуется Java 8 или совместимый поставщик JCA (например, BouncyCastle) в пути к классам среды выполнения.
Все алгоритмы управления ключами для получения ключей шифрования и дешифрования JWE:
Идентификатор | Алгоритм управления ключами |
---|---|
| RSAES-PKCS1-v1_5 |
| RSAES OAEP с использованием параметров по умолчанию |
| RSAES OAEP с использованием SHA-256 и MGF1 с SHA-256 |
| Перенос ключей AES с начальным значением по умолчанию с использованием 128-битного ключа |
| Перенос ключей AES с начальным значением по умолчанию с использованием 192-битного ключа |
| Перенос ключей AES с начальным значением по умолчанию с использованием 256-битного ключа |
| Прямое использование общего симметричного ключа в качестве CEK. |
| Эллиптическая кривая Диффи-Хеллмана Эфемерное соглашение статического ключа с использованием Concat KDF |
| ECDH-ES с использованием Concat KDF и CEK, завернутых в «A128KW». |
| ECDH-ES с использованием Concat KDF и CEK, завернутых в «A192KW». |
| ECDH-ES с использованием Concat KDF и CEK, завернутых в «A256KW». |
| Упаковка ключей с помощью AES GCM с использованием 128-битного ключа 1 |
| Упаковка ключей с помощью AES GCM с использованием 192-битного ключа 1 |
| Упаковка ключей с помощью AES GCM с использованием 256-битного ключа 1 |
| PBES2 с HMAC SHA-256 и оберткой «A128KW» 1 |
| PBES2 с HMAC SHA-384 и оберткой «A192KW» 1 |
| PBES2 с HMAC SHA-512 и оберткой «A256KW» 1 |
1 . Требуется Java 8 или совместимый поставщик JCA (например, BouncyCastle) в пути к классам среды выполнения.
Создание, анализ и проверка веб-ключей JSON (JWK) во всех стандартных форматах ключей JWA с использованием собственных типов Key
Java:
Формат ключа JWK | Тип Key Java | JJWT Тип Jwk |
---|---|---|
Симметричный ключ | | |
Открытый ключ эллиптической кривой | | |
Закрытый ключ эллиптической кривой | | |
Открытый ключ RSA | | |
Закрытый ключ RSA | | |
Закрытый ключ XDH | | |
Закрытый ключ XDH | | |
Открытый ключ EdDSA | | |
Закрытый ключ EdDSA | | |
1 . Требуется Java 15 или совместимый поставщик JCA (например, BouncyCastle) в пути к классам среды выполнения.
2 . Требуется Java 15 или совместимый поставщик JCA (например, BouncyCastle) в пути к классам среды выполнения.
Улучшения удобства, выходящие за рамки спецификации, такие как
Сжатие полезной нагрузки для любого большого JWT, а не только для JWE.
Утверждения утверждений (требуются определенные значения)
Заявить о маршалинге и демаршалинге POJO при использовании совместимого анализатора JSON (например, Джексона).
Генерация безопасного ключа на основе желаемых алгоритмов JWA
и многое другое…
Некомпактная сериализация и синтаксический анализ.
Эта функция может быть реализована в будущем выпуске. Вклад сообщества приветствуется!
Если у вас возникли проблемы с использованием JJWT, сначала прочтите документацию на этой странице, прежде чем задавать вопросы. Мы очень стараемся, чтобы документация JJWT была надежной, классифицирована с оглавлением и была актуальной для каждого выпуска.
Если документации или API JavaDoc недостаточно, и у вас есть вопросы по удобству использования или вы что-то не понимаете, задайте свой вопрос здесь. Однако:
Пожалуйста, не создавайте задачу на GitHub, чтобы задать вопрос.
Мы используем GitHub Issues для отслеживания действенной работы, требующей внесения изменений в дизайн и/или кодовую базу JJWT. Если у вас есть вопрос по удобству использования, задайте его здесь, и при необходимости мы сможем преобразовать его в проблему.
Если создается проблема GitHub, которая не представляет собой практической работы для базы кода JJWT, она будет немедленно закрыта.
Если у вас нет вопросов по удобству использования и вы считаете, что у вас есть обоснованная ошибка или запрос на добавление функции, СНАЧАЛА обсудите их здесь. Пожалуйста, сначала выполните быстрый поиск, чтобы узнать, существует ли уже существующее обсуждение, связанное с вашим, и при необходимости присоединитесь к этому существующему обсуждению.
Если вы чувствуете, что хотите помочь исправить ошибку или реализовать новую функцию самостоятельно, прочтите раздел «Вклад», прежде чем приступать к какой-либо работе.
Простые запросы на включение, которые исправляют что-либо, кроме основного кода JJWT (документацию, JavaDoc, опечатки, тестовые примеры и т. д.), всегда приветствуются и имеют высокую вероятность быстрого объединения. Пожалуйста, пришлите их!
Однако, если вы хотите или чувствуете необходимость изменить функциональность или основной код JJWT, не отправляйте запрос на включение без начала нового обсуждения JJWT и обсуждения желаемых изменений, прежде чем вы начнете над ним работать .
Было бы обидно отклонить ваш серьезный и действительно ценный запрос на включение, если он может не соответствовать целям проекта, ожиданиям от дизайна или запланированной функциональности. К сожалению, в прошлом нам приходилось отклонять крупные заявки на участие, потому что они не соответствовали ожиданиям проекта или дизайна — и все потому, что автор заявки не проверял сначала команду, прежде чем приступить к работе над решением.
Итак, сначала создайте новое обсуждение JJWT для обсуждения, а затем мы сможем легко преобразовать обсуждение в проблему, а затем посмотреть, оправдан ли (или каким образом) PR. Спасибо!
Если вы хотите помочь, но не знаете, с чего начать, посетите страницу «Вопросы, требующие помощи» и выберите любую из них, и мы будем рады обсудить и ответить на вопросы в комментариях к проблеме.
Если что-то из этого вам не подходит, не беспокойтесь! Любая помощь, которую вы хотели бы предложить, будет оценена по достоинству, учитывая приведенные выше предостережения относительно участия в запросах на включение. Не стесняйтесь обсуждать или задавать вопросы, если вы не уверены. :)
JSON Web Token (JWT) — это универсальный формат текстовых сообщений для компактной и безопасной передачи информации. Вопреки распространенному мнению, JWT полезен не только для отправки и получения токенов идентификации в Интернете, даже если это наиболее распространенный вариант использования. JWT можно использовать в качестве сообщений для любого типа данных.
JWT в своей простейшей форме состоит из двух частей:
Первичные данные в JWT, называемые payload
, и
Object
JSON с парами имя/значение, которые представляют метаданные о payload
и самом сообщении, называемый header
.
payload
JWT может быть абсолютно чем угодно — всем, что может быть представлено в виде массива байтов, например строками, изображениями, документами и т. д.
Но поскольку header
JWT является Object
JSON, было бы логично, чтобы payload
JWT также могла быть Object
JSON. Во многих случаях разработчикам нравится, чтобы payload
представляла собой JSON, который представляет данные о пользователе или компьютере или аналогичную концепцию идентификации. При таком использовании payload
называются объектом JSON Claims
, а каждая пара имя/значение в этом объекте называется claim
— каждая часть информации внутри «заявляет» что-то об идентичности.
И хотя «заявлять» что-то об идентичности полезно, на самом деле это может сделать каждый. Важно то, что вы доверяете утверждениям, проверив, что они исходят от человека или компьютера, которому вы доверяете.
Приятной особенностью JWT является то, что их можно защитить различными способами. JWT может быть криптографически подписан (что мы называем JWS) или зашифрован (что делает его JWE). Это добавляет JWT мощный уровень проверяемости — получатель JWS или JWE может иметь высокую степень уверенности, что письмо исходит от кого-то, кому он доверяет, проверяя подпись или расшифровывая ее. Именно эта особенность проверяемости делает JWT хорошим выбором для отправки и получения защищенной информации, например утверждений личности.
Наконец, JSON с пробелами для удобства чтения человеком хорош, но он не обеспечивает очень эффективный формат сообщений. Таким образом, JWT можно сжимать (и даже сжимать) до минимального представления — в основном строк в кодировке Base64URL — чтобы их можно было более эффективно передавать по сети, например, в заголовках HTTP или URL-адресах.
Если у вас есть payload
и header
, как они сжимаются для веб-передачи и как на самом деле выглядит окончательный JWT? Давайте рассмотрим упрощенную версию процесса с использованием псевдокода:
Предположим, у нас есть JWT с header
JSON и простым текстовым сообщением:
заголовок
{ "алг": "нет" }
полезная нагрузка
Истинный признак интеллекта — не знание, а воображение.
Удалите все ненужные пробелы в JSON:
String header = ' {"alg":"none"} '
String payload = ' The true sign of intelligence is not knowledge but imagination. '
Получите байты UTF-8 и кодировку Base64URL каждый:
String encodedHeader = base64URLEncode( header . getBytes( " UTF-8 " ) )
String encodedPayload = base64URLEncode( payload . getBytes( " UTF-8 " ) )
Соедините закодированный заголовок и утверждения с помощью символов точки ('.'):
String compact = encodedHeader + ' . ' + encodedPayload + ' . '
Окончательная объединенная compact
строка JWT выглядит следующим образом:
eyJhbGciOiJub25lIn0.VGhlIHRydWUgc2lnbiBvZiBpbnRlbGxpZ2VuY2UgaXMgbm90IGtub3dsZWRnZSBidXQgaW1hZ2luYXRpb24u.
Это называется «незащищенным» JWT, потому что не используется никакая безопасность — нет цифровых подписей или шифрования для «защиты» JWT, чтобы гарантировать, что он не может быть изменен третьими лицами.
Если бы мы хотели поставить цифровую подпись на компактной форме, чтобы мы могли, по крайней мере, гарантировать, что никто не изменит данные без нашего обнаружения, нам пришлось бы выполнить еще несколько шагов, показанных далее.
Вместо полезных данных в виде обычного текста в следующем примере будет использоваться, вероятно, наиболее распространенный тип полезных данных — Object
утверждений JSON, содержащий информацию об определенном удостоверении. Мы также подпишем JWT цифровой подписью, чтобы гарантировать, что он не может быть изменен третьей стороной без нашего ведома.
Предположим, у нас есть header
JSON и payload
претензий:
заголовок
{
"alg" : " HS256 "
}
полезная нагрузка
{
"sub" : " Joe "
}
В этом случае header
указывает, что для криптографической подписи JWT будет использоваться алгоритм HS256
(HMAC с использованием SHA-256). Кроме того, объект JSON payload
имеет единственное утверждение, sub
со значением Joe
.
В спецификации имеется ряд стандартных претензий, называемых зарегистрированными претензиями, и sub
(от «Субъект») является одним из них.
Удалите все ненужные пробелы в обоих объектах JSON:
String header = ' {"alg":"HS256"} '
String claims = ' {"sub":"Joe"} '
Получите их байты UTF-8 и кодировку Base64URL каждый:
String encodedHeader = base64URLEncode( header . getBytes( " UTF-8 " ) )
String encodedClaims = base64URLEncode( claims . getBytes( " UTF-8 " ) )
Объедините закодированный заголовок и утверждения с помощью символа точки «.». разделитель:
String concatenated = encodedHeader + ' . ' + encodedClaims
Используйте достаточно надежный криптографический секретный или закрытый ключ вместе с выбранным вами алгоритмом подписи (здесь мы будем использовать HMAC-SHA-256) и подпишите объединенную строку:
SecretKey key = getMySecretKey()
byte [] signature = hmacSha256( concatenated, key )
Поскольку подписи всегда представляют собой массивы байтов, Base64URL кодирует подпись и присоединяет ее к concatenated
строке с символом точки «.». разделитель:
String compact = concatenated + ' . ' + base64URLEncode( signature )
И вот, окончательная compact
строка выглядит так:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60AlD4
Это называется «JWS» — сокращение от подписанного JWT.
Конечно, никто не захочет делать это вручную в коде, и, что еще хуже, если вы сделаете что-то не так, вы можете создать серьезные проблемы с безопасностью и уязвимости. В результате был создан JJWT, чтобы справиться со всем этим за вас: JJWT полностью автоматизирует как создание JWS, так и анализ и проверку JWS.
До сих пор мы видели незащищенный JWT и JWT с криптографической подписью (называемый «JWS»). Одна из особенностей, присущая обоим этим двум, заключается в том, что вся информация в них может быть просмотрена кем угодно — все данные как в заголовке, так и в полезных данных общедоступны. JWS просто гарантирует, что данные никем не были изменены, и не мешает никому их видеть. Во многих случаях это нормально, поскольку содержащиеся в них данные не являются конфиденциальной информацией.
Но что, если вам нужно представить в JWT информацию, которая считается конфиденциальной — например, чей-то почтовый адрес, номер социального страхования или номер банковского счета?
В этих случаях нам нужен полностью зашифрованный JWT, для краткости называемый «JWE». JWE использует криптографию, чтобы гарантировать, что полезная нагрузка остается полностью зашифрованной и аутентифицированной, поэтому посторонние лица не смогут увидеть данные внутри или изменить данные, не будучи обнаруженными. В частности, спецификация JWE требует, чтобы для полного шифрования и защиты данных использовались алгоритмы Authenticated Encryption with Associated Data.
Полный обзор алгоритмов AEAD выходит за рамки этой документации, но вот пример окончательного компактного JWE, использующего эти алгоритмы (переносы строк предназначены только для удобства чтения):
eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0. 6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ. AxY8DCtDaGlsbGljb3RoZQ. KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY. U0m_YmjN04DJvceFICbCVQ
Далее мы рассмотрим, как установить JJWT в ваш проект, а затем увидим, как использовать удобный API-интерфейс JJWT вместо рискованных манипуляций со строками для быстрого и безопасного создания JWT, JWS и JWE.
Используйте свой любимый Maven-совместимый инструмент сборки, чтобы извлечь зависимости из Maven Central.
Зависимости могут немного отличаться, если вы работаете с проектом JDK или проектом Android.
Если вы создаете проект JDK (не для Android), вам потребуется определить следующие зависимости:
< dependency >
< groupId >io.jsonwebtoken</ groupId >
< artifactId >jjwt-api</ artifactId >
< version >0.12.6</ version >
</ dependency >
< dependency >
< groupId >io.jsonwebtoken</ groupId >
< artifactId >jjwt-impl</ artifactId >
< version >0.12.6</ version >
< scope >runtime</ scope >
</ dependency >
< dependency >
< groupId >io.jsonwebtoken</ groupId >
< artifactId >jjwt-jackson</ artifactId > <!-- or jjwt-gson if Gson is preferred -->
< version >0.12.6</ version >
< scope >runtime</ scope >
</ dependency >
<!-- Uncomment this next dependency if you are using:
- JDK 10 or earlier, and you want to use RSASSA-PSS (PS256, PS384, PS512) signature algorithms.
- JDK 10 or earlier, and you want to use EdECDH (X25519 or X448) Elliptic Curve Diffie-Hellman encryption.
- JDK 14 or earlier, and you want to use EdDSA (Ed25519 or Ed448) Elliptic Curve signature algorithms.
It is unnecessary for these algorithms on JDK 15 or later.
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId> or bcprov-jdk15to18 on JDK 7
<version>1.76</version>
<scope>runtime</scope>
</dependency>
-->
dependencies {
implementation ' io.jsonwebtoken:jjwt-api:0.12.6 '
runtimeOnly ' io.jsonwebtoken:jjwt-impl:0.12.6 '
runtimeOnly ' io.jsonwebtoken:jjwt-jackson:0.12.6 ' // or 'io.jsonwebtoken:jjwt-gson:0.12.6' for gson
/*
Uncomment this next dependency if you are using:
- JDK 10 or earlier, and you want to use RSASSA-PSS (PS256, PS384, PS512) signature algorithms.
- JDK 10 or earlier, and you want to use EdECDH (X25519 or X448) Elliptic Curve Diffie-Hellman encryption.
- JDK 14 or earlier, and you want to use EdDSA (Ed25519 or Ed448) Elliptic Curve signature algorithms.
It is unnecessary for these algorithms on JDK 15 or later.
*/
// runtimeOnly 'org.bouncycastle:bcprov-jdk18on:1.76' // or bcprov-jdk15to18 on JDK 7
}
В проектах Android потребуется определить следующие зависимости и исключения Proguard, а также необязательный Provider
BouncyCastle:
Добавьте зависимости в ваш проект:
dependencies {
api( ' io.jsonwebtoken:jjwt-api:0.12.6 ' )
runtimeOnly( ' io.jsonwebtoken:jjwt-impl:0.12.6 ' )
runtimeOnly( ' io.jsonwebtoken:jjwt-orgjson:0.12.6 ' ) {
exclude( group : ' org.json ' , module : ' json ' ) // provided by Android natively
}
/*
Uncomment this next dependency if you want to use:
- RSASSA-PSS (PS256, PS384, PS512) signature algorithms.
- EdECDH (X25519 or X448) Elliptic Curve Diffie-Hellman encryption.
- EdDSA (Ed25519 or Ed448) Elliptic Curve signature algorithms.
** AND ALSO ensure you enable the BouncyCastle provider as shown below **
*/
// implementation('org.bouncycastle:bcprov-jdk18on:1.76') // or bcprov-jdk15to18 for JDK 7
}
Вы можете использовать следующие правила исключения Android Proguard:
-keeppattributes Внутренние классы -сохранить класс io.jsonwebtoken.** { *; } -keepnames class io.jsonwebtoken.* { *; } -keepnames интерфейс io.jsonwebtoken.* { *; } -keep class org.bouncycastle.** { *; } -keepnames класс org.bouncycastle.** { *; } -dontwarn org.bouncycastle.**
Если вы хотите использовать алгоритмы JWT RSASSA-PSS (т. е. PS256
, PS384
и PS512
), EdECDH ( X25512
или X448
) шифрование Диффи-Хеллмана с эллиптической кривой, алгоритмы подписи EdDSA ( Ed25519
или Ed448
) или вы просто хотите гарантировать, что ваш Android приложение использует обновленную версию BouncyCastle, вам необходимо:
Раскомментируйте зависимость BouncyCastle, как указано выше в разделе зависимостей.
Замените устаревший пользовательский поставщик BC
для Android обновленным.
Регистрация поставщика должна быть выполнена на ранних стадиях жизненного цикла приложения, предпочтительно в основном классе Activity
вашего приложения в виде статического блока инициализации. Например:
class MainActivity : AppCompatActivity () {
companion object {
init {
Security .removeProvider( " BC " ) // remove old/legacy Android-provided BC provider
Security .addProvider( BouncyCastleProvider ()) // add 'real'/correct BC provider
}
}
// ... etc ...
}
Обратите внимание, что все приведенные выше объявления зависимостей JJWT имеют только одну зависимость времени компиляции, а остальные объявляются как зависимости времени выполнения .
Это связано с тем, что JJWT спроектирован таким образом, что вы зависите только от тех API, которые явно предназначены для использования в ваших приложениях, а все другие детали внутренней реализации, которые могут измениться без предупреждения, отнесены к зависимостям только во время выполнения. Это чрезвычайно важный момент, если вы хотите обеспечить стабильное использование JJWT и его обновления с течением времени:
JJWT гарантирует совместимость семантического управления версиями для всех своих артефактов, за исключением |
Это сделано для вашей пользы: большое внимание уделяется курированию jjwt-api
и обеспечению того, чтобы он содержал все, что вам нужно, и оставался обратно совместимым, насколько это возможно, чтобы вы могли безопасно рассчитывать на это в области компиляции. Стратегия jjwt-impl
.jar во время выполнения предоставляет разработчикам JJWT возможность изменять внутренние пакеты и реализации в любое время и в любом случае. Это помогает нам реализовывать функции, исправлять ошибки и доставлять вам новые выпуски быстрее и эффективнее.
Большая часть сложности скрыта за удобным и читаемым свободным интерфейсом на основе конструктора, который отлично подходит для использования автодополнения IDE для быстрого написания кода. Вот пример:
import io . jsonwebtoken . Jwts ;
import io . jsonwebtoken . security . Keys ;
import java . security . Key ;
// We need a signing key, so we'll create one just for this example. Usually
// the key would be read from your application configuration instead.
SecretKey key = Jwts . SIG . HS256 . key (). build ();
String jws = Jwts . builder (). subject ( "Joe" ). signWith ( key ). compact ();
Как это было легко!?
В данном случае мы:
создание JWT, в котором в качестве зарегистрированного sub
утверждения (Subject) будет установлено значение Joe
. Мы тогда
подписание JWT с использованием ключа, подходящего для алгоритма HMAC-SHA-256. Наконец, мы
уплотняя его в окончательную String
форму. Подписанный JWT называется «JWS».
Результирующая строка jws
выглядит следующим образом:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60AlD4
Теперь давайте проверим JWT (вы всегда должны отбрасывать JWT, которые не соответствуют ожидаемой подписи):
assert Jwts . parser (). verifyWith ( key ). build (). parseSignedClaims ( jws ). getPayload (). getSubject (). equals ( "Joe" );
Здесь происходят две вещи. Предыдущий key
используется для проверки подписи JWT. Если не удается проверить JWT, генерируется SignatureException
(который расширяет JwtException
). Предполагая, что JWT проверен, мы анализируем утверждения и утверждаем, что для этого субъекта установлено значение Joe
. Вы должны любить однострочники кода, которые впечатляют!
ПРИМЕЧАНИЕ | Типобезопасные JWT: чтобы получить типобезопасный результат |
Но что, если синтаксический анализ или проверка подписи не удались? Вы можете перехватить JwtException
и отреагировать соответствующим образом:
try {
Jwts . parser (). verifyWith ( key ). build (). parseSignedClaims ( compactJws );
//OK, we can trust this JWT
} catch ( JwtException e ) {
//don't trust the JWT!
}
Теперь, когда мы познакомились с тем, как создавать и анализировать JWT, давайте более подробно рассмотрим API JJWT.
Вы создаете JWT следующим образом:
Используйте метод Jwts.builder()
для создания экземпляра JwtBuilder
.
При желании установите любые параметры header
по желанию.
Вызовите методы построителя, чтобы установить содержимое полезных данных или утверждения.
При необходимости вызовите методы signWith
или encryptWith
если вы хотите поставить цифровую подпись или зашифровать JWT.
Вызовите метод compact()
чтобы получить результирующую компактную строку JWT.
Например:
String jwt = Jwts . builder () // (1)
. header () // (2) optional
. keyId ( "aKeyId" )
. and ()
. subject ( "Bob" ) // (3) JSON Claims, or
//.content(aByteArray, "text/plain") // any byte[] content, with media type
. signWith ( signingKey ) // (4) if signing, or
//.encryptWith(key, keyAlg, encryptionAlg) // if encrypting
. compact (); // (5)
payload
JWT может быть либо содержимым byte[]
(через content
) , либо утверждениями JSON (например, subject
, claims
и т. д.), но не тем и другим одновременно.
Можно использовать либо цифровые подписи ( signWith
), либо шифрование ( encryptWith
), но не то и другое.
Незащищенные JWT : если вы не используете методы компоновщика |
Заголовок JWT — это Object
JSON, который предоставляет метаданные о содержимом, формате и любых криптографических операциях, относящихся к payload
JWT. JJWT предоставляет несколько способов установки всего заголовка и/или нескольких отдельных параметров заголовка (пар имя/значение).
Самый простой и рекомендуемый способ установить один или несколько параметров заголовка JWT (пары имя/значение) — использовать конструктор header()
JwtBuilder
по желанию, а затем вызвать его метод and()
, чтобы вернуться обратно в JwtBuilder
для дальнейшей настройки. . Например:
String jwt = Jwts . builder ()
. header () // <----
. keyId ( "aKeyId" )
. x509Url ( aUri )
. add ( "someName" , anyValue )
. add ( mapValues )