JJWT vise à être la bibliothèque la plus simple à utiliser et à comprendre pour créer et vérifier des jetons Web JSON (JWT) et des clés Web JSON (JWK) sur JVM et Android.
JJWT est une implémentation purement Java basée exclusivement sur les spécifications RFC du groupe de travail JOSE :
RFC 7519 : Jeton Web JSON (JWT)
RFC 7515 : Signature Web JSON (JWS)
RFC 7516 : chiffrement Web JSON (JWE)
RFC 7517 : clé Web JSON (JWK)
RFC 7518 : algorithmes Web JSON (JWA)
RFC 7638 : Empreinte de clé Web JSON
RFC 9278 : URI d'empreinte de clé Web JSON
RFC 7797 : option de charge utile non codée JWS
RFC 8037 : algorithmes d'Edwards Curve et JWK
Il a été créé par Les Hazlewood et est soutenu et maintenu par une communauté de contributeurs.
JJWT est open source selon les termes de la licence Apache 2.0.
PublicKey
JWK privéetoString()
SécuritéEntièrement fonctionnel sur tous les JDK Java 7+ et Android
Meilleures pratiques et assertions de sécurité automatiques
API facile à apprendre et à lire
Interfaces fluides pratiques et lisibles, idéales pour la saisie semi-automatique de l'IDE afin d'écrire du code rapidement
Entièrement conforme aux spécifications RFC sur toutes les fonctionnalités implémentées, testées par rapport aux vecteurs de test spécifiés par RFC
Implémentation stable avec près de 1 700 tests et couverture du code de test imposée à 100 %. Chaque méthode, instruction et variante de branche conditionnelle dans l'ensemble de la base de code est testée et doit être transmise à chaque build.
Création, analyse et vérification de JWT compacts signés numériquement (alias JWS) avec tous les algorithmes JWS standard :
Identifiant | Algorithme de signature |
---|---|
| HMAC utilisant SHA-256 |
| HMAC utilisant SHA-384 |
| HMAC utilisant SHA-512 |
| ECDSA utilisant P-256 et SHA-256 |
| ECDSA utilisant P-384 et SHA-384 |
| ECDSA utilisant P-521 et SHA-512 |
| RSASSA-PKCS-v1_5 utilisant SHA-256 |
| RSASSA-PKCS-v1_5 utilisant SHA-384 |
| RSASSA-PKCS-v1_5 utilisant SHA-512 |
| RSASSA-PSS utilisant SHA-256 et MGF1 avec SHA-256 1 |
| RSASSA-PSS utilisant SHA-384 et MGF1 avec SHA-384 1 |
| RSASSA-PSS utilisant SHA-512 et MGF1 avec SHA-512 1 |
| Algorithme de signature numérique à courbe d'Edwards 2 |
1. Nécessite Java 11 ou un fournisseur JCA compatible (comme BouncyCastle) dans le chemin de classe d'exécution.
2 . Nécessite Java 15 ou un fournisseur JCA compatible (comme BouncyCastle) dans le chemin de classe d'exécution.
Création, analyse et déchiffrement de JWT compacts chiffrés (alias JWE) avec tous les algorithmes de chiffrement JWE standard :
Identifiant | Algorithme de cryptage |
---|---|
| Algorithme de chiffrement authentifié AES_128_CBC_HMAC_SHA_256 |
| Algorithme de chiffrement authentifié AES_192_CBC_HMAC_SHA_384 |
| Algorithme de chiffrement authentifié AES_256_CBC_HMAC_SHA_512 |
| AES GCM utilisant la clé 1 de 128 bits |
| AES GCM utilisant la clé 1 de 192 bits |
| AES GCM utilisant la clé 1 de 256 bits |
1 . Nécessite Java 8 ou un fournisseur JCA compatible (comme BouncyCastle) dans le chemin de classe d'exécution.
Tous les algorithmes de gestion de clés pour obtenir les clés de chiffrement et de déchiffrement JWE :
Identifiant | Algorithme de gestion des clés |
---|---|
| RSAES-PKCS1-v1_5 |
| RSAES OAEP utilisant les paramètres par défaut |
| RSAES OAEP utilisant SHA-256 et MGF1 avec SHA-256 |
| AES Key Wrap avec valeur initiale par défaut utilisant une clé de 128 bits |
| AES Key Wrap avec valeur initiale par défaut utilisant une clé de 192 bits |
| AES Key Wrap avec valeur initiale par défaut utilisant une clé de 256 bits |
| Utilisation directe d'une clé symétrique partagée comme le CEK |
| Accord de clé statique éphémère Diffie-Hellman à courbe elliptique utilisant Concat KDF |
| ECDH-ES utilisant Concat KDF et CEK enveloppés avec "A128KW" |
| ECDH-ES utilisant Concat KDF et CEK enveloppés avec "A192KW" |
| ECDH-ES utilisant Concat KDF et CEK enveloppés avec "A256KW" |
| Encapsulation de clé avec AES GCM à l'aide de la clé 1 de 128 bits |
| Encapsulation de clé avec AES GCM à l'aide de la clé 1 de 192 bits |
| Encapsulation de clé avec AES GCM à l'aide de la clé 1 de 256 bits |
| PBES2 avec HMAC SHA-256 et emballage "A128KW" 1 |
| PBES2 avec HMAC SHA-384 et emballage "A192KW" 1 |
| PBES2 avec HMAC SHA-512 et emballage "A256KW" 1 |
1 . Nécessite Java 8 ou un fournisseur JCA compatible (comme BouncyCastle) dans le chemin de classe d'exécution.
Création, analyse et vérification de clés Web JSON (JWK) dans tous les formats de clés JWA standard à l'aide de types Key
Java natifs :
Format de clé JWK | Type Key Java | Type de Jwk JJWT |
---|---|---|
Clé symétrique | | |
Clé publique de courbe elliptique | | |
Clé privée de courbe elliptique | | |
Clé publique RSA | | |
Clé privée RSA | | |
Clé privée XDH | | |
Clé privée XDH | | |
Clé publique EdDSA | | |
Clé privée EdDSA | | |
1 . Nécessite Java 15 ou un fournisseur JCA compatible (comme BouncyCastle) dans le chemin de classe d'exécution.
2 . Nécessite Java 15 ou un fournisseur JCA compatible (comme BouncyCastle) dans le chemin de classe d'exécution.
Améliorations de commodité au-delà des spécifications telles que
Compression de la charge utile pour tout grand JWT, pas seulement pour les JWE
Assertions de revendications (nécessitant des valeurs spécifiques)
Réclamez le marshaling et le démarshalling POJO lors de l'utilisation d'un analyseur JSON compatible (par exemple Jackson)
Génération de clé sécurisée basée sur les algorithmes JWA souhaités
et plus encore…
Sérialisation et analyse non compactes.
Cette fonctionnalité pourrait être implémentée dans une prochaine version. Les contributions de la communauté sont les bienvenues !
Si vous rencontrez des difficultés pour utiliser JJWT, veuillez d'abord lire la documentation sur cette page avant de poser des questions. Nous essayons très fort de garantir que la documentation de JJWT est robuste, classée avec une table des matières et à jour pour chaque version.
Si la documentation ou l'API JavaDoc ne suffit pas et que vous avez des questions sur l'utilisabilité ou que vous êtes confus à propos de quelque chose, veuillez poser votre question ici. Cependant:
Veuillez ne pas créer de problème GitHub pour poser une question.
Nous utilisons les problèmes GitHub pour suivre les travaux exploitables qui nécessitent des modifications de la conception et/ou de la base de code de JJWT. Si vous avez une question sur l'utilisabilité, veuillez plutôt poser votre question ici, et nous pourrons la convertir en problème si nécessaire.
Si un problème GitHub est créé et ne représente pas un travail exploitable pour la base de code de JJWT, il sera rapidement fermé.
Si vous n'avez pas de question sur l'utilisabilité et pensez avoir une demande légitime de bogue ou de fonctionnalité, veuillez en discuter ici D'ABORD . Veuillez d'abord effectuer une recherche rapide pour voir si une discussion existante liée à la vôtre existe déjà et rejoindre cette discussion existante si nécessaire.
Si vous souhaitez aider à corriger un bug ou implémenter la nouvelle fonctionnalité vous-même, veuillez lire la section Contribuer ensuite avant de commencer tout travail.
Les demandes d'extraction simples qui corrigent autre chose que le code principal de JJWT (documentation, JavaDoc, fautes de frappe, cas de test, etc.) sont toujours appréciées et ont de fortes chances d'être fusionnées rapidement. S'il vous plaît, envoyez-les !
Cependant, si vous souhaitez ou ressentez le besoin de modifier les fonctionnalités ou le code principal de JJWT, veuillez ne pas émettre de demande d'extraction sans démarrer une nouvelle discussion sur JJWT et sans discuter d'abord des modifications souhaitées, avant de commencer à travailler dessus .
Il serait dommage de rejeter votre pull request sérieuse et véritablement appréciée si elle risque de ne pas correspondre aux objectifs du projet, aux attentes de conception ou aux fonctionnalités prévues. Nous avons malheureusement dû rejeter des PR importants dans le passé parce qu'ils n'étaient pas synchronisés avec les attentes du projet ou de la conception - tout cela parce que l'auteur du PR n'avait pas d'abord vérifié auprès de l'équipe avant de travailler sur une solution.
Alors, veuillez d'abord créer une nouvelle discussion JJWT pour en discuter, puis nous pourrons facilement convertir la discussion en problème, puis voir si (ou comment) un PR est justifié. Merci!
Si vous souhaitez aider, mais ne savez pas par où commencer, veuillez visiter la page Problèmes recherchés et choisissez l'un d'entre eux. Nous serons heureux d'en discuter et de répondre aux questions dans les commentaires du problème.
Si l’un d’entre eux ne vous intéresse pas, ne vous inquiétez pas ! Toute aide que vous souhaiteriez offrir serait appréciée sur la base des mises en garde ci-dessus concernant la contribution aux demandes d'extraction. N'hésitez pas à discuter ou à poser des questions en premier si vous n'êtes pas sûr. :)
JSON Web Token (JWT) est un format de messagerie texte à usage général permettant de transmettre des informations de manière compacte et sécurisée. Contrairement à la croyance populaire, JWT n'est pas seulement utile pour envoyer et recevoir des jetons d'identité sur le Web, même s'il s'agit du cas d'utilisation le plus courant. Les JWT peuvent être utilisés comme messages pour tout type de données.
Un JWT dans sa forme la plus simple contient deux parties :
Les données principales du JWT, appelées payload
, et
Un Object
JSON avec des paires nom/valeur qui représentent des métadonnées sur la payload
et le message lui-même, appelé header
.
Une payload
JWT peut être absolument n'importe quoi : tout ce qui peut être représenté sous forme de tableau d'octets, comme des chaînes, des images, des documents, etc.
Mais comme un header
JWT est un Object
JSON, il serait logique qu'une payload
JWT puisse également être un Object
JSON. Dans de nombreux cas, les développeurs préfèrent que la payload
soit du type JSON qui représente des données sur un utilisateur ou un ordinateur ou un concept d'identité similaire. Lorsqu'elle est utilisée de cette manière, la payload
est appelée un objet JSON Claims
, et chaque paire nom/valeur au sein de cet objet est appelée une claim
- chaque élément d'information contenu dans « revendique » quelque chose sur une identité.
Et même s’il est utile de « revendiquer » quelque chose sur une identité, n’importe qui peut le faire. Ce qui est important, c'est que vous fassiez confiance aux affirmations en vérifiant qu'elles proviennent d'une personne ou d'un ordinateur en qui vous avez confiance.
Une caractéristique intéressante des JWT est qu’ils peuvent être sécurisés de différentes manières. Un JWT peut être signé cryptographiquement (ce qui en fait ce que nous appelons un JWS) ou crypté (ce qui en fait un JWE). Cela ajoute une puissante couche de vérifiabilité au JWT : un destinataire JWS ou JWE peut avoir un degré élevé de confiance qu'il provient d'une personne de confiance en vérifiant une signature ou en la déchiffrant. C'est cette fonctionnalité de vérifiabilité qui fait de JWT un bon choix pour envoyer et recevoir des informations sécurisées, comme les réclamations d'identité.
Enfin, JSON avec des espaces pour une lisibilité humaine est agréable, mais cela ne constitue pas un format de message très efficace. Par conséquent, les JWT peuvent être compactés (et même compressés) en une représentation minimale - essentiellement des chaînes codées en Base64URL - afin qu'ils puissent être transmis plus efficacement sur le Web, comme dans les en-têtes HTTP ou les URL.
Une fois que vous avez une payload
et header
, comment sont-ils compactés pour la transmission Web et à quoi ressemble réellement le JWT final ? Passons en revue une version simplifiée du processus avec un pseudocode :
Supposons que nous ayons un JWT avec un header
JSON et une simple charge utile de message texte :
en-tête
{ "alg": "aucun" }
charge utile
Le véritable signe de l’intelligence n’est pas la connaissance mais l’imagination.
Supprimez tous les espaces inutiles dans le JSON :
String header = ' {"alg":"none"} '
String payload = ' The true sign of intelligence is not knowledge but imagination. '
Obtenez chacun les octets UTF-8 et l'encodage Base64URL :
String encodedHeader = base64URLEncode( header . getBytes( " UTF-8 " ) )
String encodedPayload = base64URLEncode( payload . getBytes( " UTF-8 " ) )
Joignez l'en-tête codé et les revendications avec des points ('.') :
String compact = encodedHeader + ' . ' + encodedPayload + ' . '
La chaîne JWT compact
concaténée finale ressemble à ceci :
eyJhbGciOiJub25lIn0.VGhlIHRydWUgc2lnbiBvZiBpbnRlbGxpZ2VuY2UgaXMgbm90IGtub3dsZWRnZSBidXQgaW1hZ2luYXRpb24u.
C'est ce qu'on appelle un JWT « non protégé » car aucune sécurité n'est impliquée : pas de signature numérique ni de cryptage pour « protéger » le JWT afin de garantir qu'il ne puisse pas être modifié par des tiers.
Si nous voulions signer numériquement le formulaire compact afin de pouvoir au moins garantir que personne ne modifie les données sans que nous le détections, nous devrions effectuer quelques étapes supplémentaires, illustrées ci-dessous.
Au lieu d'une charge utile en texte brut, l'exemple suivant utilisera probablement le type de charge utile le plus courant : un Object
de réclamation JSON contenant des informations sur une identité particulière. Nous signerons également numériquement le JWT pour nous assurer qu'il ne peut pas être modifié par un tiers à notre insu.
Supposons que nous ayons un header
JSON et une payload
de revendications :
en-tête
{
"alg" : " HS256 "
}
charge utile
{
"sub" : " Joe "
}
Dans ce cas, l' header
indique que l'algorithme HS256
(HMAC utilisant SHA-256) sera utilisé pour signer cryptographiquement le JWT. De plus, l'objet JSON payload
a une seule revendication, sub
avec la valeur Joe
.
Il existe un certain nombre de revendications standards, appelées revendications enregistrées, dans la spécification et sub
(pour « sujet ») en fait partie.
Supprimez tous les espaces inutiles dans les deux objets JSON :
String header = ' {"alg":"HS256"} '
String claims = ' {"sub":"Joe"} '
Obtenez chacun leurs octets UTF-8 et leur encodage Base64URL :
String encodedHeader = base64URLEncode( header . getBytes( " UTF-8 " ) )
String encodedClaims = base64URLEncode( claims . getBytes( " UTF-8 " ) )
Concaténez l'en-tête codé et les revendications avec un point '.' délimiteur :
String concatenated = encodedHeader + ' . ' + encodedClaims
Utilisez un secret cryptographique ou une clé privée suffisamment forte, ainsi qu'un algorithme de signature de votre choix (nous utiliserons ici HMAC-SHA-256), et signez la chaîne concaténée :
SecretKey key = getMySecretKey()
byte [] signature = hmacSha256( concatenated, key )
Étant donné que les signatures sont toujours des tableaux d'octets, encodez la signature en Base64URL et joignez-la à la chaîne concatenated
avec un point '.' délimiteur :
String compact = concatenated + ' . ' + base64URLEncode( signature )
Et voilà, la chaîne compact
finale ressemble à ceci :
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60AlD4
C'est ce qu'on appelle un « JWS » – abréviation de JWT signé .
Bien sûr, personne ne voudrait le faire manuellement dans le code, et pire encore, si vous vous trompez, vous pourriez introduire de graves problèmes et faiblesses de sécurité. En conséquence, JJWT a été créé pour gérer tout cela pour vous : JJWT automatise complètement à la fois la création de JWS ainsi que l'analyse et la vérification des JWS pour vous.
Jusqu'à présent, nous avons vu un JWT non protégé et un JWT signé cryptographiquement (appelé « JWS »). L'une des choses inhérentes à ces deux éléments est que toutes les informations qu'ils contiennent peuvent être vues par n'importe qui - toutes les données de l'en-tête et de la charge utile sont visibles publiquement. JWS garantit simplement que les données n'ont été modifiées par personne - cela n'empêche personne de les voir. Souvent, c’est très bien car les données qu’ils contiennent ne sont pas des informations sensibles.
Mais que se passe-t-il si vous avez besoin de représenter dans un JWT des informations considérées comme sensibles - peut-être l'adresse postale, le numéro de sécurité sociale ou le numéro de compte bancaire d'une personne ?
Dans ces cas, nous voudrions un JWT entièrement crypté, appelé « JWE » en abrégé. Un JWE utilise la cryptographie pour garantir que la charge utile reste entièrement cryptée et authentifiée afin que les parties non autorisées ne puissent pas voir les données ni les modifier sans être détectées. Plus précisément, la spécification JWE exige que des algorithmes de chiffrement authentifié avec données associées soient utilisés pour chiffrer et protéger entièrement les données.
Un aperçu complet des algorithmes AEAD sort du cadre de cette documentation, mais voici un exemple de JWE compact final qui utilise ces algorithmes (les sauts de ligne sont uniquement destinés à la lisibilité) :
eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0. 6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ. AxY8DCtDaGlsbGljb3RoZQ. KDlTtXchhZTGufMYmOYGS4HffxPSURfmqCHXaI9wOGY. U0m_YmjN04DJvceFICbCVQ
Nous verrons ensuite comment installer JJWT dans votre projet, puis nous verrons comment utiliser l'API fluide et agréable de JJWT au lieu d'une manipulation de chaîne risquée pour créer rapidement et en toute sécurité des JWT, JWS et JWE.
Utilisez votre outil de construction compatible Maven préféré pour extraire les dépendances de Maven Central.
Les dépendances peuvent différer légèrement si vous travaillez avec un projet JDK ou un projet Android.
Si vous créez un projet JDK (non Android), vous souhaiterez définir les dépendances suivantes :
< 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
}
Les projets Android voudront définir les dépendances et exclusions Proguard suivantes, ainsi que Provider
BouncyCastle facultatif :
Ajoutez les dépendances à votre projet :
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
}
Vous pouvez utiliser les règles d'exclusion Android Proguard suivantes :
-keepattributes Classes intérieures -garder la classe io.jsonwebtoken.** { *; } -keepnames classe io.jsonwebtoken.* { *; } -keepnames interface io.jsonwebtoken.* { *; } -garder la classe org.bouncycastle.** { *; } -keepnames class org.bouncycastle.** { *; } -ne pas avertir org.bouncycastle.**
Si vous souhaitez utiliser les algorithmes JWT RSASSA-PSS (c'est-à-dire PS256
, PS384
et PS512
), le cryptage EdECDH ( X25512
ou X448
) Elliptic Curve Diffie-Hellman, les algorithmes de signature EdDSA ( Ed25519
ou Ed448
), ou si vous souhaitez simplement vous assurer que votre Android Si l'application exécute une version mise à jour de BouncyCastle, vous devrez :
Décommentez la dépendance BouncyCastle comme commenté ci-dessus dans la section dépendances.
Remplacez l’ancien fournisseur BC
personnalisé Android par celui mis à jour.
L'enregistrement du fournisseur doit être effectué au début du cycle de vie de l'application, de préférence dans la classe Activity
principale de votre application en tant que bloc d'initialisation statique. Par exemple:
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 ...
}
Notez que les déclarations de dépendances JJWT ci-dessus n'ont toutes qu'une seule dépendance au moment de la compilation et les autres sont déclarées comme dépendances d'exécution .
En effet, JJWT est conçu pour que vous ne dépendiez que des API explicitement conçues pour que vous puissiez les utiliser dans vos applications et que tous les autres détails d'implémentation internes - qui peuvent changer sans avertissement - sont relégués aux dépendances d'exécution uniquement. C'est un point extrêmement important si vous souhaitez garantir une utilisation stable de JJWT et des mises à niveau dans le temps :
JJWT garantit la compatibilité de version sémantique pour tous ses artefacts à l'exception du |
Ceci est fait pour votre bénéfice : un grand soin est apporté à la conservation du jjwt-api
.jar et à la garantie qu'il contient ce dont vous avez besoin et reste compatible avec les versions antérieures autant que possible afin que vous puissiez en dépendre en toute sécurité avec la portée de la compilation. La stratégie d'exécution jjwt-impl
.jar offre aux développeurs JJWT la flexibilité de modifier les packages internes et les implémentations chaque fois que cela est nécessaire. Cela nous aide à implémenter des fonctionnalités, à corriger des bugs et à vous envoyer de nouvelles versions plus rapidement et plus efficacement.
La plus grande complexité est cachée derrière une interface fluide, pratique et lisible, basée sur un constructeur, idéale pour s'appuyer sur la saisie semi-automatique de l'IDE pour écrire du code rapidement. Voici un exemple :
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 ();
C'était facile !?
Dans ce cas, nous sommes :
créer un JWT dont le sub
réclamation enregistré (Sujet) sera défini sur Joe
. Nous sommes alors
signer le JWT à l'aide d'une clé adaptée à l'algorithme HMAC-SHA-256. Enfin, nous sommes
en le compactant dans sa forme String
finale. Un JWT signé est appelé « JWS ».
La chaîne jws
résultante ressemble à ceci :
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60AlD4
Vérifions maintenant le JWT (vous devez toujours supprimer les JWT qui ne correspondent pas à une signature attendue) :
assert Jwts . parser (). verifyWith ( key ). build (). parseSignedClaims ( jws ). getPayload (). getSubject (). equals ( "Joe" );
Il se passe deux choses ici. La key
précédente est utilisée pour vérifier la signature du JWT. S'il ne parvient pas à vérifier le JWT, une SignatureException
(qui étend JwtException
) est levée. En supposant que le JWT soit vérifié, nous analysons les revendications et affirmons que ce sujet est défini sur Joe
. Vous devez aimer les one-liners de code qui ont du punch !
NOTE | JWT de type sécurisé : pour obtenir un résultat |
Mais que se passe-t-il si l’analyse ou la validation de la signature échoue ? Vous pouvez attraper JwtException
et réagir en conséquence :
try {
Jwts . parser (). verifyWith ( key ). build (). parseSignedClaims ( compactJws );
//OK, we can trust this JWT
} catch ( JwtException e ) {
//don't trust the JWT!
}
Maintenant que nous avons eu un aperçu rapide de la façon de créer et d'analyser des JWT, couvrons l'API de JJWT en profondeur.
Vous créez un JWT comme suit :
Utilisez la méthode Jwts.builder()
pour créer une instance JwtBuilder
.
Définissez éventuellement les paramètres header
comme vous le souhaitez.
Appelez les méthodes du générateur pour définir le contenu ou les revendications de la charge utile.
Appelez éventuellement les méthodes signWith
ou encryptWith
si vous souhaitez signer ou chiffrer numériquement le JWT.
Appelez la méthode compact()
pour produire la chaîne JWT compacte résultante.
Par exemple:
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)
La payload
JWT peut être soit du contenu byte[]
(via content
) soit des revendications JSON (telles que subject
, claims
, etc.), mais pas les deux.
Des signatures numériques ( signWith
) ou un chiffrement ( encryptWith
) peuvent être utilisés, mais pas les deux.
JWT non protégés : si vous n'utilisez pas les méthodes de création |
Un en-tête JWT est un Object
JSON qui fournit des métadonnées sur le contenu, le format et toutes les opérations cryptographiques pertinentes pour la payload
JWT. JJWT propose un certain nombre de façons de définir l'intégralité de l'en-tête et/ou plusieurs paramètres d'en-tête individuels (paires nom/valeur).
Le moyen le plus simple et recommandé de définir un ou plusieurs paramètres d'en-tête JWT (paires nom/valeur) consiste à utiliser le générateur header()
de JwtBuilder
comme vous le souhaitez, puis d'appeler sa méthode and()
pour revenir à JwtBuilder
pour une configuration plus approfondie. . Par exemple:
String jwt = Jwts . builder ()
. header () // <----
. keyId ( "aKeyId" )
. x509Url ( aUri )
. add ( "someName" , anyValue )
. add ( mapValues )