Guía completa para usar JJWT

JJWT, es una biblioteca JSON Web Token (JWT) para Java y Android.
JJWT, también conocido como Java JWT, el nombre completo es Java JSON Web Token.
JJWT se basa completamente en las especificaciones RFC JWT, JWS, JWE, JWK y JWA y es de código abierto bajo los términos de la licencia Apache 2.0. Creada por el arquitecto senior de Okta, Les Hazlewood, la biblioteca cuenta con el apoyo y el mantenimiento de una comunidad de contribuyentes.
JJWT se mantiene en GitHub, la dirección es https://github.com/jwtk/jjwt , no tiene un sitio web dedicado y la documentación de desarrollo no es muy rica.

Ventajas de JJWT

  • pleno funcionamiento
  • Seguridad
  • Desarrollo de interfaz de streaming, conveniente y legible. Hay una función de finalización automática de código en el IDE
  • Totalmente compatible con las especificaciones RFC
  • Cobertura de prueba de código del 100%
  • Cree, analice y verifique JWT compactos firmados digitalmente utilizando todos los algoritmos JWS estándar

Algoritmo de firma JJWT

Identificador algoritmo de firma
HS256 HMAC usando SHA-256
HS384 HMAC usando SHA-384
HS512 HMAC usando SHA-512
ES256 ECDSA usando P-256 y SHA-256
ES384 ECDSA usando P-384 y SHA-384
ES512 ECDSA usando P-512 y SHA-512
RS256 RSASSA-PKCS-v1_5 usando SHA-256
RS384 RSASSA-PKCS-v1_5 usando SHA-384
RS512 RSASSA-PKCS-v1_5 usando SHA-512
PS256 RSASSA-PSS para SHA-256 y MGF1 con SHA-256
PS384 RSASSA-PSS usando SHA-384 y MGF1 con SHA-384
PS512 RSASSA-PSS usando SHA-512 y MGF1 con SHA-512
EdDSA Algoritmo de firma digital de curva de Edwards
  • HMAC (Código de autenticación de mensajes basado en hash) es un algoritmo de código de autenticación de mensajes basado en una función hash. Utiliza una clave secreta y el mensaje de entrada como entrada, y genera un código de autenticación de longitud fija realizando una operación de función hash específica. HMAC se puede utilizar para verificar la integridad de un mensaje y verificar la identidad de la fuente del mensaje.
  • Cree, analice y descifre JWT compactos cifrados utilizando todos los algoritmos de cifrado JWE estándar
  • Todos los algoritmos de gestión de claves utilizados para obtener claves de cifrado y descifrado JWE
  • Cree, analice y valide claves web JSON (JWK) en todos los formatos de claves JWA estándar utilizando tipos de claves Java nativas.

Importación de dependencia JJWT

Agregue la siguiente configuración al pom.xml del proyecto:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>JJWT_RELEASE_VERSION</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>JJWT_RELEASE_VERSION</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
    <version>JJWT_RELEASE_VERSION</version>
    <scope>runtime</scope>
</dependency>


  • JJWT_RELEASE_VERSION corresponde a la versión de lanzamiento de JJWT. La última versión es 0.11.5. Para conocer la versión de lanzamiento de JJWT, consulte: https://github.com/jwtk/jjwt/tags
  • Debido a que JWT transfiere datos en formato JSON, el paquete JSON utilizado aquí es jackson. Si desea utilizar el paquete JSON de Gson, puede importar jjwt-gson

Si tiene los siguientes escenarios de uso, deberá importar adicionalmente la biblioteca bcprov-jdk15on

  • JDK 10 o versión anterior, es necesario utilizar el algoritmo de firma RSASSA-PSS (PS256, PS384, PS512)
  • JDK 10 o versiones anteriores deben utilizar el cifrado Diffie-Hellman de curva elíptica EdECDH (X25519 o X448).
  • JDK14 o versiones anteriores deben utilizar el algoritmo de firma de curva elíptica EdDSA (Ed25519 o Ed448).
    Nota: si es JDK15 y versiones posteriores, no es necesario agregar

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
    <scope>runtime</scope>
</dependency>

Por qué el alcance de jjwt-impl es el tiempo de ejecución

JJWT garantiza la compatibilidad de versiones semánticas para todos los artefactos excepto jjwt-impl.jar. No existe tal garantía para jjwt-impl .jar y pueden ocurrir cambios internos en el .jar en cualquier momento. Nunca agregue jjwt-impl .jar a un proyecto con alcance de compilación; declarelo siempre con alcance de tiempo de ejecución.

Ejemplo de JJWT

Un token JWT firmado:

	@Test
	public void genJws() {	
		//1. 产生令牌
		SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256); //HMAC-SHA-256
		String jws = Jwts.builder().setSubject("Osxm").signWith(key).compact();		
		System.out.println("jws="+jws);
		
		//2. 解析令牌
		String str = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(jws).getBody().getSubject();
		System.out.println(str);
	}
  • JWT firmado, si la clave de firma no se establece al analizar, se generará el siguiente error: java.lang.IllegalArgumentException: A signing key must be specified if the specified JWT is digitally signed.
  • Por lo tanto, puede juzgar si se trata de un token de firma válido detectando excepciones.

Establecer encabezado JWT

El encabezado JWT es un objeto JSON que proporciona metadatos sobre el contenido, el formato y cualquier operación criptográfica asociada con la carga útil de JWT. JJWT proporciona varias formas de configurar el encabezado completo y/o múltiples parámetros de encabezado individuales (pares de nombre/valor).
Los parámetros de encabezado se pueden agregar usando setHeaderParam().

	@Test
	public void setHeader() {
		SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256); 
		String jws = Jwts.builder()
				.setHeaderParam("head1", "head1 value")
				.setHeaderParam("head2", "head2 value")
				.setSubject("Osxm").signWith(key).compact();
		System.out.println("jws="+jws);
	}

carga

establecer texto normal

String jwt = Jwts.builder().setPayload("普通文本的负载").compact();

La carga útil del JWT puede contener una afirmación o declaración del destinatario del JWT, en lugar de una matriz de bytes de contenido. En este caso, la carga útil es un objeto JSON de reclamos y JJWT admite la creación de reclamos utilizando métodos de creación de tipos seguros.

	@Test
	public void payload() {
		Date now = new Date();
		String jwt = Jwts.builder().setPayload("普通文本的负载").compact();
		 Jwts.builder()
		 .setIssuer("Osxm")
		 .setSubject("Demo JWT")
		 .setAudience("ITs")
		 .setExpiration(new Date(now.getTime() + 3600 * 1000)) //过期时间, 1小时
		 .setNotBefore(now) //最早生效时间
		 .setIssuedAt(now)
		 .setId(UUID.randomUUID().toString())
		 .compact();
		 
	}
  • En JSON Web Tokens (JWT), "notBefore" (nbf) es una afirmación estándar de que el token no se considera válido hasta entonces. Indica el momento más temprano (en segundos o una fecha y hora específicas) en que se puede usar o aceptar un token.

Agregue otras declaraciones:

.claim("myname", "myvalue")

clave de firma

clave de firma

Firmar un JWT con una clave pública no es seguro. JJWT rechazará cualquier PublicKey especificada para firmar y lanzará InvalidKeyException.

####Formato SecretKey
Utilice el algoritmo HMAC-SHA para firmar el JWS. Si configura la cadena de clave o la matriz de bytes codificados usted mismo, debe convertirla en una instancia de SecretKey y utilizarla como parámetro del método signWith.

JWE: JWT totalmente cifrado

En el ejemplo anterior, el JWT en sí no está protegido y la firma está protegida mediante cifrado (JWS). Se pueden ver los datos del encabezado y la carga útil, y la firma digital puede garantizar que no haya sido manipulada.
Sin embargo, en algunos escenarios, la carga útil contendrá información confidencial. Esto requiere un JWT completamente cifrado, llamado "JWE". NOSOTROS utilizamos cifrado para garantizar que la carga útil permanezca completamente cifrada y autenticada, de modo que partes no autorizadas no puedan ver los datos que contiene ni modificarlos sin ser detectados. Específicamente, la especificación JWE requiere cifrado autenticado utilizando algoritmos de datos vinculados para cifrar y proteger completamente los datos.

Dependiendo del formato de la clave,

  • Matriz de bytes codificados:  SecretKey key = Keys.hmacShaKeyFor(encodedKeyBytes);
  • Cadena codificada en base 64:SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secretString));
  • Cadena codificada en Base64URL:SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64URL.decode(secretString));
  • Cadenas sin formato (sin codificar) (por ejemplo, cadenas de contraseña):SecretKey key = Keys.hmacShaKeyFor(secretString.getBytes(StandardCharsets.UTF_8));

Nota: El método secretString.getBytes() (sin proporcionar el juego de caracteres) está obsoleto. Además, el uso de la cadena de contraseña original conducirá inevitablemente a claves débiles o sensibles, así que intente utilizar claves aleatorias seguras.

@Test
	public void key() {
		//1. 方式1 ,使用密码字符串的字节数组
		String mykeyString = "thisismykeythisismykeythisismykeythisismykey";
		Key secretKey = Keys.hmacShaKeyFor(mykeyString.getBytes(StandardCharsets.UTF_8));
		
		//2. 使用Java本身获取
		Key secretKey2 = new SecretKeySpec(mykeyString.getBytes(StandardCharsets.UTF_8),"HmacSHA256");
		
		//3. JJWT的SignatureAlgorithm
		Key secretKey3 = new SecretKeySpec(mykeyString.getBytes(StandardCharsets.UTF_8), SignatureAlgorithm.HS256.getJcaName());
		
		//4. 随机字符串
		Key secretKey4 = Keys.secretKeyFor(SignatureAlgorithm.HS256);
		String keyString =  Encoders.BASE64.encode(secretKey4.getEncoded());
		System.out.println("keyString="+keyString);
	}

Compresión JWT

Si la carga útil del JWT es grande (contiene muchos datos), es necesario comprimir el JWT para reducir su tamaño. Tenga en cuenta que esta no es una característica estándar de todos los JWT (solo JWE) y es poco probable que otras bibliotecas JWT admitan tokens que no sean JWE. Sin embargo, JJWT admite la compresión de JWS y JWE.
Estándar no JWS: JJWT admite la compresión JWS, pero no es una característica estándar de JWS. La especificación JWT RFC solo estandariza esto para JWE y es poco probable que otras bibliotecas JWT para JWS lo admitan. Utilice la compresión JWS solo si está seguro de que JJWT (u otra biblioteca que admita la compresión JWS) analizará el JWS.

leer JWT


		Jws<Claims> jws = Jwts.parserBuilder().setSigningKey(mykeyString.getBytes(StandardCharsets.UTF_8)).build().parseClaimsJws(jwsString);
		String issuer = jws.getBody().getIssuer();
		System.out.println("issuer="+issuer);







// 创建JWT解析器,并设置签名密钥解析器
JwtParser jwtParser = Jwts.parserBuilder()
                        .setSigningKeyResolver(new SigningKeyResolverAdapter() {
                            @Override
                            public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {
                                // 在这里实现自定义的签名密钥解析逻辑,并返回解析的密钥
                                // ...
                            }
                        })
                        .build();

// 使用解析器解析JWT
Jws<Claims> jws = jwtParser.parseClaimsJws(jwt);
Claims claims = jws.getBody();



Supongo que te gusta

Origin blog.csdn.net/oscar999/article/details/132462214
Recomendado
Clasificación