JJWT pretende ser la biblioteca más fácil de usar y comprender para crear y verificar tokens web JSON (JWT) y claves web JSON (JWK) en JVM y Android.
JJWT es una implementación Java pura basada exclusivamente en las especificaciones RFC del JOSE Working Group:
RFC 7519: Token web JSON (JWT)
RFC 7515: Firma web JSON (JWS)
RFC 7516: Cifrado web JSON (JWE)
RFC 7517: clave web JSON (JWK)
RFC 7518: Algoritmos web JSON (JWA)
RFC 7638: Huella digital de clave web JSON
RFC 9278: URI de huella digital de clave web JSON
RFC 7797: Opción de carga útil sin codificar JWS
RFC 8037: algoritmos de la curva de Edwards y JWK
Fue creado por Les Hazlewood y cuenta con el respaldo y mantenimiento de una comunidad de colaboradores.
JJWT es de código abierto según los términos de la licencia Apache 2.0.
PublicKey
JWK privadatoString()
SeguridadTotalmente funcional en todos los JDK de Java 7+ y Android
Mejores prácticas y afirmaciones de seguridad automática
API fácil de aprender y leer
Interfaces fluidas, cómodas y legibles, ideales para el autocompletado de IDE para escribir código rápidamente
Totalmente compatible con la especificación RFC en todas las funciones implementadas, probadas con vectores de prueba especificados por RFC
Implementación estable con casi 1700 pruebas y cobertura de código de prueba del 100%. Cada método, declaración y variante de rama condicional en todo el código base se prueba y se requiere que se transmita en cada compilación.
Creación, análisis y verificación de JWT compactos firmados digitalmente (también conocidos como JWS) con todos los algoritmos JWS estándar:
Identificador | Algoritmo de firma |
---|---|
| HMAC usando SHA-256 |
| HMAC usando SHA-384 |
| HMAC usando SHA-512 |
| ECDSA usando P-256 y SHA-256 |
| ECDSA usando P-384 y SHA-384 |
| ECDSA usando P-521 y SHA-512 |
| RSASSA-PKCS-v1_5 usando SHA-256 |
| RSASSA-PKCS-v1_5 usando SHA-384 |
| RSASSA-PKCS-v1_5 usando SHA-512 |
| RSASSA-PSS usando SHA-256 y MGF1 con SHA-256 1 |
| RSASSA-PSS usando SHA-384 y MGF1 con SHA-384 1 |
| RSASSA-PSS usando SHA-512 y MGF1 con SHA-512 1 |
| Algoritmo 2 de firma digital de la curva de Edwards |
1. Requiere Java 11 o un proveedor JCA compatible (como BouncyCastle) en la ruta de clases en tiempo de ejecución.
2 . Requiere Java 15 o un proveedor JCA compatible (como BouncyCastle) en la ruta de clases en tiempo de ejecución.
Creación, análisis y descifrado de JWT compactos cifrados (también conocidos como JWE) con todos los algoritmos de cifrado JWE estándar:
Identificador | Algoritmo de cifrado |
---|---|
| Algoritmo de cifrado autenticado AES_128_CBC_HMAC_SHA_256 |
| Algoritmo de cifrado autenticado AES_192_CBC_HMAC_SHA_384 |
| Algoritmo de cifrado autenticado AES_256_CBC_HMAC_SHA_512 |
| AES GCM usando la clave 1 de 128 bits |
| AES GCM usando la clave 1 de 192 bits |
| AES GCM usando la clave 1 de 256 bits |
1 . Requiere Java 8 o un proveedor JCA compatible (como BouncyCastle) en la ruta de clases en tiempo de ejecución.
Todos los algoritmos de gestión de claves para obtener claves de cifrado y descifrado JWE:
Identificador | Algoritmo de gestión de claves |
---|---|
| RSAES-PKCS1-v1_5 |
| RSAES OAEP usando parámetros predeterminados |
| RSAES OAEP usando SHA-256 y MGF1 con SHA-256 |
| Ajuste de clave AES con valor inicial predeterminado utilizando una clave de 128 bits |
| Ajuste de clave AES con valor inicial predeterminado usando una clave de 192 bits |
| Ajuste de clave AES con valor inicial predeterminado usando una clave de 256 bits |
| Uso directo de una clave simétrica compartida como CEK |
| Acuerdo de clave estática efímera de curva elíptica Diffie-Hellman utilizando Concat KDF |
| ECDH-ES usando Concat KDF y CEK envuelto con "A128KW" |
| ECDH-ES usando Concat KDF y CEK envuelto con "A192KW" |
| ECDH-ES usando Concat KDF y CEK envuelto con "A256KW" |
| Ajuste de claves con AES GCM usando la clave 1 de 128 bits |
| Ajuste de claves con AES GCM usando la clave 1 de 192 bits |
| Ajuste de claves con AES GCM usando la clave 1 de 256 bits |
| PBES2 con HMAC SHA-256 y envoltura "A128KW" 1 |
| PBES2 con HMAC SHA-384 y envoltura "A192KW" 1 |
| PBES2 con HMAC SHA-512 y envoltura "A256KW" 1 |
1 . Requiere Java 8 o un proveedor JCA compatible (como BouncyCastle) en la ruta de clases en tiempo de ejecución.
Creación, análisis y verificación de claves web JSON (JWK) en todos los formatos de claves JWA estándar utilizando tipos Key
Java nativas:
Formato de clave JWK | Tipo Key Java | Tipo Jwk JJWT |
---|---|---|
Clave simétrica | | |
Clave pública de curva elíptica | | |
Clave privada de curva elíptica | | |
Clave pública RSA | | |
Clave privada RSA | | |
Clave privada XDH | | |
Clave privada XDH | | |
Clave pública EdDSA | | |
Clave privada de EdDSA | | |
1 . Requiere Java 15 o un proveedor JCA compatible (como BouncyCastle) en la ruta de clases en tiempo de ejecución.
2 . Requiere Java 15 o un proveedor JCA compatible (como BouncyCastle) en la ruta de clases en tiempo de ejecución.
Mejoras de comodidad más allá de las especificaciones, como
Compresión de carga útil para cualquier JWT grande, no solo para JWE
Afirmaciones de reclamos (que requieren valores específicos)
Reclamar clasificación y desclasificación de POJO cuando se utiliza un analizador JSON compatible (por ejemplo, Jackson)
Generación segura de claves basada en los algoritmos JWA deseados
y más…
Serialización y análisis no compactos.
Esta característica puede implementarse en una versión futura. ¡Las contribuciones de la comunidad son bienvenidas!
Si tiene problemas para usar JJWT, primero lea la documentación en esta página antes de hacer preguntas. Nos esforzamos mucho para garantizar que la documentación de JJWT sea sólida, esté categorizada con una tabla de contenido y esté actualizada para cada versión.
Si la documentación o el API JavaDoc no es suficiente y tiene preguntas sobre usabilidad o está confundido acerca de algo, haga su pregunta aquí. Sin embargo:
No cree un problema de GitHub para hacer una pregunta.
Usamos GitHub Issues para rastrear el trabajo procesable que requiere cambios en el diseño y/o el código base de JJWT. Si tiene una pregunta sobre usabilidad, haga su pregunta aquí y podremos convertirla en un problema si es necesario.
Si se crea un problema de GitHub que no representa un trabajo procesable para el código base de JJWT, se cerrará de inmediato.
Si no tiene una pregunta sobre usabilidad y cree que tiene un error legítimo o una solicitud de función, discútalo aquí PRIMERO . Primero haga una búsqueda rápida para ver si ya existe una discusión relacionada con la suya y únase a esa discusión existente si es necesario.
Si cree que le gustaría ayudar a corregir un error o implementar la nueva función usted mismo, lea la sección Contribuciones a continuación antes de comenzar cualquier trabajo.
Las solicitudes de extracción simples que corrigen cualquier cosa que no sea el código central de JJWT (documentación, JavaDoc, errores tipográficos, casos de prueba, etc.) siempre se agradecen y tienen una alta probabilidad de fusionarse rápidamente. ¡Por favor envíelos!
Sin embargo, si desea o siente la necesidad de cambiar la funcionalidad o el código principal de JJWT, no emita una solicitud de extracción sin iniciar una nueva discusión sobre JJWT y discutir primero los cambios deseados, antes de comenzar a trabajar en ello .
Sería una pena rechazar su solicitud de extracción sincera y genuinamente apreciada si no se alinea con los objetivos del proyecto, las expectativas de diseño o la funcionalidad planificada. Lamentablemente, hemos tenido que rechazar grandes relaciones públicas en el pasado porque no estaban sincronizadas con las expectativas del proyecto o diseño, todo porque el autor de relaciones públicas no se comunicó primero con el equipo antes de trabajar en una solución.
Por lo tanto, primero cree una nueva discusión de JJWT para discutir, y luego podremos ver fácilmente cómo convertir la discusión en un problema y luego ver si (o cómo) se justifica un PR. ¡Gracias!
Si desea ayudar, pero no sabe por dónde empezar, visite la página Problemas buscados por ayuda y elija cualquiera de los que aparecen allí. Estaremos encantados de discutir y responder preguntas en los comentarios del problema.
Si alguno de ellos no te atrae, ¡no te preocupes! Cualquier ayuda que desee ofrecer será apreciada según las advertencias anteriores sobre la contribución de solicitudes de extracción. Siéntase libre de discutir o hacer preguntas primero si no está seguro. :)
JSON Web Token (JWT) es un formato de mensajería basado en texto de uso general para transmitir información de forma compacta y segura. Contrariamente a la creencia popular, JWT no sólo es útil para enviar y recibir tokens de identidad en la web, incluso si ese es el caso de uso más común. Los JWT se pueden utilizar como mensajes para cualquier tipo de datos.
Un JWT en su forma más simple contiene dos partes:
Los datos primarios dentro del JWT, llamados payload
, y
Un Object
JSON con pares de nombre/valor que representan metadatos sobre la payload
y el mensaje en sí, llamado header
.
Una payload
JWT puede ser absolutamente cualquier cosa: cualquier cosa que pueda representarse como una matriz de bytes, como cadenas, imágenes, documentos, etc.
Pero debido a que un header
JWT es un Object
JSON, tendría sentido que una payload
JWT también pudiera ser un Object
JSON. En muchos casos, a los desarrolladores les gusta que la payload
sea JSON que represente datos sobre un usuario o computadora o un concepto de identidad similar. Cuando se usa de esta manera, la payload
se llama objeto JSON Claims
, y cada par de nombre/valor dentro de ese objeto se llama claim
: cada pieza de información dentro de 'reclama' algo sobre una identidad.
Y si bien es útil "reivindicar" algo sobre una identidad, en realidad cualquiera puede hacerlo. Lo importante es que confíes en las afirmaciones verificando que provengan de una persona o computadora en la que confíes.
Una característica interesante de los JWT es que se pueden proteger de varias maneras. Un JWT puede estar firmado criptográficamente (convirtiéndolo en lo que llamamos un JWS) o cifrado (convirtiéndolo en un JWE). Esto agrega una poderosa capa de verificabilidad al JWT: un destinatario de JWS o JWE puede tener un alto grado de confianza de que proviene de alguien en quien confía al verificar una firma o descifrarla. Es esta característica de verificabilidad la que hace que JWT sea una buena opción para enviar y recibir información segura, como declaraciones de identidad.
Finalmente, JSON con espacios en blanco para facilitar la lectura humana es bueno, pero no constituye un formato de mensaje muy eficiente. Por lo tanto, los JWT se pueden compactar (e incluso comprimir) a una representación mínima (básicamente cadenas codificadas en Base64URL) para que puedan transmitirse por la web de manera más eficiente, como en encabezados HTTP o URL.
Una vez que tenga una payload
y header
, ¿cómo se compactan para la transmisión web y cómo se ve realmente el JWT final? Veamos una versión simplificada del proceso con algún pseudocódigo:
Supongamos que tenemos un JWT con un header
JSON y una carga útil de mensaje de texto simple:
encabezamiento
{ "alg": "ninguno" }
carga útil
El verdadero signo de la inteligencia no es el conocimiento sino la imaginación.
Elimine todos los espacios en blanco innecesarios en el JSON:
String header = ' {"alg":"none"} '
String payload = ' The true sign of intelligence is not knowledge but imagination. '
Obtenga los bytes UTF-8 y la codificación Base64URL cada uno:
String encodedHeader = base64URLEncode( header . getBytes( " UTF-8 " ) )
String encodedPayload = base64URLEncode( payload . getBytes( " UTF-8 " ) )
Une el encabezado codificado y los reclamos con caracteres de punto ('.'):
String compact = encodedHeader + ' . ' + encodedPayload + ' . '
La cadena JWT compact
concatenada final tiene este aspecto:
eyJhbGciOiJub25lIn0.VGhlIHRydWUgc2lnbiBvZiBpbnRlbGxpZ2VuY2UgaXMgbm90IGtub3dsZWRnZSBidXQgaW1hZ2luYXRpb24u.
Esto se denomina JWT "desprotegido" porque no interviene ninguna seguridad: no hay firmas digitales ni cifrado para "proteger" el JWT y garantizar que terceros no puedan modificarlo.
Si quisiéramos firmar digitalmente el formulario compacto para al menos poder garantizar que nadie cambie los datos sin que lo detectemos, tendríamos que realizar algunos pasos más, que se muestran a continuación.
En lugar de una carga útil de texto sin formato, el siguiente ejemplo utilizará probablemente el tipo de carga útil más común: un Object
JSON que contiene información sobre una identidad particular. También firmaremos digitalmente el JWT para garantizar que un tercero no pueda modificarlo sin que nosotros lo sepamos.
Supongamos que tenemos un header
JSON y una payload
de reclamos:
encabezamiento
{
"alg" : " HS256 "
}
carga útil
{
"sub" : " Joe "
}
En este caso, el header
indica que se utilizará el algoritmo HS256
(HMAC usando SHA-256) para firmar criptográficamente el JWT. Además, el objeto JSON payload
tiene un único reclamo, sub
con valor Joe
.
Hay una serie de reclamaciones estándar, denominadas Reclamaciones Registradas, en la especificación y sub
(para 'Asunto') es uno de ellos.
Elimine todos los espacios en blanco innecesarios en ambos objetos JSON:
String header = ' {"alg":"HS256"} '
String claims = ' {"sub":"Joe"} '
Obtenga sus bytes UTF-8 y codificación Base64URL cada uno:
String encodedHeader = base64URLEncode( header . getBytes( " UTF-8 " ) )
String encodedClaims = base64URLEncode( claims . getBytes( " UTF-8 " ) )
Concatene el encabezado codificado y los reclamos con un carácter de punto '.' delimitador:
String concatenated = encodedHeader + ' . ' + encodedClaims
Utilice un secreto criptográfico o una clave privada suficientemente sólida, junto con un algoritmo de firma de su elección (aquí usaremos HMAC-SHA-256) y firme la cadena concatenada:
SecretKey key = getMySecretKey()
byte [] signature = hmacSha256( concatenated, key )
Debido a que las firmas son siempre matrices de bytes, codifique la firma en Base64URL y únala a la cadena concatenated
con un carácter de punto '.' delimitador:
String compact = concatenated + ' . ' + base64URLEncode( signature )
Y ahí lo tienes, el String compact
final se ve así:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60AlD4
Esto se llama 'JWS', abreviatura de JWT firmado .
Por supuesto, nadie querría hacer esto manualmente en el código y, peor aún, si comete algún error, podría introducir graves problemas y debilidades de seguridad. Como resultado, JJWT se creó para manejar todo esto por usted: JJWT automatiza completamente tanto la creación de JWS como el análisis y la verificación de JWS por usted.
Hasta ahora hemos visto un JWT desprotegido y un JWT firmado criptográficamente (llamado 'JWS'). Una de las cosas inherentes a ambos es que cualquiera puede ver toda la información que contienen: todos los datos tanto en el encabezado como en la carga útil son visibles públicamente. JWS simplemente garantiza que nadie haya cambiado los datos; no impide que nadie los vea. Muchas veces, esto está bien porque los datos que contienen no son información confidencial.
Pero, ¿qué pasaría si necesitara representar información en un JWT que se considera información confidencial, tal vez la dirección postal, el número de seguro social o el número de cuenta bancaria de alguien?
En estos casos, querríamos un JWT completamente cifrado, llamado 'JWE' para abreviar. Un JWE utiliza criptografía para garantizar que la carga útil permanezca completamente cifrada y autenticada para que partes no autorizadas no puedan ver los datos que contiene ni cambiarlos sin ser detectados. Específicamente, la especificación JWE requiere que se utilicen algoritmos de cifrado autenticado con datos asociados para cifrar y proteger completamente los datos.
Una descripción general completa de los algoritmos AEAD está fuera del alcance de esta documentación, pero aquí hay un ejemplo de un JWE compacto final que utiliza estos algoritmos (los saltos de línea son solo para facilitar la lectura):
eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0. 6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ. AxY8DCtDaGlsbGljb3RoZQ. KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY. U0m_YmjN04DJvceFICbCVQ
A continuación, cubriremos cómo instalar JJWT en su proyecto, y luego veremos cómo usar la API fluida y agradable de JJWT en lugar de la manipulación arriesgada de cadenas para construir JWT, JWS y JWE de forma rápida y segura.
Utilice su herramienta de compilación compatible con Maven favorita para extraer las dependencias de Maven Central.
Las dependencias pueden diferir ligeramente si está trabajando con un proyecto JDK o un proyecto de Android.
Si está creando un proyecto JDK (que no sea de Android), querrá definir las siguientes dependencias:
< 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
}
Los proyectos de Android querrán definir las siguientes dependencias y exclusiones de Proguard, y Provider
BouncyCastle opcional:
Agregue las dependencias a su proyecto:
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
}
Puede utilizar las siguientes reglas de exclusión de Android Proguard:
-keepattributes clases internas -mantener clase io.jsonwebtoken.** { *; } -keepnames clase io.jsonwebtoken.* { *; } -keepnames interfaz io.jsonwebtoken.* { *; } -mantener clase org.bouncycastle.** { *; } -keepnames clase org.bouncycastle.** { *; } -dontwarn org.bouncycastle.**
Si desea utilizar algoritmos JWT RSASSA-PSS (es decir, PS256
, PS384
y PS512
), cifrado EdECDH ( X25512
o X448
), curva elíptica Diffie-Hellman, algoritmos de firma EdDSA ( Ed25519
o Ed448
), o simplemente desea garantizar que su Android La aplicación ejecuta una versión actualizada de BouncyCastle, deberá:
Descomente la dependencia de BouncyCastle como se comentó anteriormente en la sección de dependencias.
Reemplace el proveedor BC
personalizado de Android heredado por el actualizado.
El registro del proveedor debe realizarse al principio del ciclo de vida de la aplicación, preferiblemente en la clase Activity
principal de su aplicación como un bloque de inicialización estático. Por ejemplo:
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 ...
}
Observe que todas las declaraciones de dependencia de JJWT anteriores tienen solo una dependencia en tiempo de compilación y el resto se declaran como dependencias en tiempo de ejecución .
Esto se debe a que JJWT está diseñado para que usted solo dependa de las API que están diseñadas explícitamente para su uso en sus aplicaciones y todos los demás detalles de implementación interna (que pueden cambiar sin previo aviso) quedan relegados a dependencias de solo tiempo de ejecución. Este es un punto extremadamente importante si desea garantizar un uso estable de JJWT y actualizaciones a lo largo del tiempo:
JJWT garantiza compatibilidad de versiones semánticas para todos sus artefactos excepto |
Esto se hace para beneficiarlo: se pone mucho cuidado en seleccionar el jjwt-api
.jar y garantizar que contenga lo que necesita y que siga siendo compatible con versiones anteriores tanto como sea posible para que pueda confiar en él de forma segura con el alcance de la compilación. La estrategia jjwt-impl
.jar en tiempo de ejecución brinda a los desarrolladores de JJWT la flexibilidad de cambiar los paquetes internos y las implementaciones cuando y como sea necesario. Esto nos ayuda a implementar funciones, corregir errores y enviarle nuevas versiones de manera más rápida y eficiente.
La mayor parte de la complejidad se esconde detrás de una interfaz fluida basada en un constructor conveniente y legible, ideal para confiar en el autocompletado de IDE para escribir código rápidamente. He aquí un ejemplo:
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 ();
¿¡Qué fácil fue eso!?
En este caso somos:
construyendo un JWT que tendrá el sub
reclamo registrado (Asunto) establecido en Joe
. entonces somos
firmar el JWT utilizando una clave adecuada para el algoritmo HMAC-SHA-256. Finalmente, estamos
compactándolo en su forma final String
. Un JWT firmado se denomina 'JWS'.
La cadena jws
resultante se ve así:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60AlD4
Ahora verifiquemos el JWT (siempre debes descartar los JWT que no coincidan con la firma esperada):
assert Jwts . parser (). verifyWith ( key ). build (). parseSignedClaims ( jws ). getPayload (). getSubject (). equals ( "Joe" );
Aquí están sucediendo dos cosas. La key
anterior se utiliza para verificar la firma del JWT. Si no se puede verificar el JWT, se lanza una SignatureException
(que extiende JwtException
). Suponiendo que el JWT esté verificado, analizamos las afirmaciones y afirmamos que ese asunto está configurado en Joe
. ¡Tienes que amar los códigos ingeniosos que tienen un gran impacto!
NOTA | JWT con seguridad de tipos: para obtener un resultado JWT |
Pero, ¿qué pasa si falla el análisis o la validación de la firma? Puede detectar JwtException
y reaccionar en consecuencia:
try {
Jwts . parser (). verifyWith ( key ). build (). parseSignedClaims ( compactJws );
//OK, we can trust this JWT
} catch ( JwtException e ) {
//don't trust the JWT!
}
Ahora que hemos probado rápidamente cómo crear y analizar JWT, cubramos la API de JJWT en profundidad.
Creas un JWT de la siguiente manera:
Utilice el método Jwts.builder()
para crear una instancia JwtBuilder
.
Opcionalmente, configure los parámetros header
como desee.
Llame a los métodos del creador para configurar el contenido de la carga útil o las reclamaciones.
Opcionalmente, llame a los métodos signWith
o encryptWith
si desea firmar o cifrar digitalmente el JWT.
Llame al método compact()
para producir la cadena JWT compacta resultante.
Por ejemplo:
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 puede ser contenido de byte[]
(a través de content
) o reclamos JSON (como subject
, claims
, etc.), pero no ambos.
Se pueden utilizar firmas digitales ( signWith
) o cifrado ( encryptWith
), pero no ambas.
JWT desprotegidos : si no utiliza los métodos del constructor |
Un encabezado JWT es un Object
JSON que proporciona metadatos sobre el contenido, el formato y cualquier operación criptográfica relevante para la payload
de JWT. JJWT proporciona varias formas de configurar el encabezado completo y/o múltiples parámetros de encabezado individuales (pares nombre/valor).
La forma más fácil y recomendada de configurar uno o más parámetros de encabezado JWT (pares nombre/valor) es usar el constructor header()
de JwtBuilder
como se desee y luego llamar a su método and()
para regresar a JwtBuilder
para realizar más configuraciones. . Por ejemplo:
String jwt = Jwts . builder ()
. header () // <----
. keyId ( "aKeyId" )
. x509Url ( aUri )
. add ( "someName" , anyValue )
. add ( mapValues )