Explicación detallada de la autenticación de token basada en JWT (implementación de Java)

Explicación detallada de la autenticación de token basada en JWT (implementación de Java)

Consejos antes de ver:

La versión de IDEA utilizada en este artículo es la última 2019.1, y la versión JDK es 1.8.0_141.

1. Introducción

En la autenticación de identidad por computadora, significa token (temporal). El token es en realidad más popular y se puede llamar código secreto. Antes de alguna transmisión de datos, el código secreto debe verificarse primero. Se autorizan diferentes códigos secretos para diferentes operaciones de datos.

2.JWT

JSON Web Token, JSON Web token, nuestro siguiente ejemplo también se basa en la autenticación de token implementada por JWT, la siguiente es una cadena JWT completa

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODMyOTQxNzEsInVzZXJOYW1lIjoidXNlciIsInBhc3N3b3JkIjoiMTExMTExMTEifQ.t6JLktclylpt2s5T_B1KDxYCJALr-fbZsy1J_YT57Jk

Se compone de tres partes: encabezado, carga útil y firma

2.1 encabezado

Consta de dos partes

  1. El tipo de declaración es JWT.

  2. Declare el algoritmo de cifrado, use HMAC SHA256

La parte del encabezado JWT es un objeto JSON, como se muestra a continuación

{
	'typ': 'JWT',
	'alg': 'HS256'
}

Cifrelo con Base64, luego JWT constituye la primera parte.

2.2 carga útil

La parte de carga útil es la parte de contenido principal del JWT y también es un objeto JSON, compuesto por tres partes

  1. Declaración registrada en el estándar

  2. Declaración pública

  3. Declaración privada

La declaración registrada en el estándar proporciona siete campos predeterminados.

  1. iss: emisor

  2. exp: tiempo de vencimiento

  3. sub: Asunto

  4. aud: usuario

  5. nbf: No disponible antes

  6. iat: tiempo de liberación

  7. jti: el ID de JWT se utiliza para identificar el JWT

Declaración pública

La declaración pública puede agregar cualquier información, generalmente agregando información relacionada con el usuario u otra información necesaria requerida por la empresa (no se recomienda información confidencial).

Declaración privada

Una declaración privada es una declaración definida conjuntamente por el proveedor y el consumidor (no se recomienda información sensible).

El siguiente ejemplo es una carga útil de muestra

{
	"sub": "1234567890",
	"name": "userName",
	"admin": true
}

Cifrelo con Base64 para formar la segunda parte de JWT.

Nota: JWT no está encriptado por defecto y cualquiera puede interpretar su contenido, por lo tanto, no construya campos de información privada y almacene información confidencial para evitar la filtración de información.

2.3 firma

La parte del hash de la firma es firmar las dos partes de datos anteriores y generar un hash a través del algoritmo especificado para garantizar que los datos no sean alterados. Consta de tres partes:

  1. encabezado (cifrado por Base64)

  2. payload (encriptado en Base64)

  3. secreto

El servidor necesita una clave secreta, que solo se almacena en el servidor y no se puede revelar a los usuarios. Luego, use el algoritmo de firma especificado en el encabezado (HMAC SHA256 por defecto) para generar una firma de acuerdo con la siguiente fórmula.

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

Después de que se calcula el hash de la firma, las tres partes del encabezado JWT, la carga útil y el hash de la firma se combinan en una cadena, y cada parte está separada por "." Para formar el objeto JWT completo.

3. Utilice

El cliente recibe el JWT devuelto por el servidor y lo almacena en Cookie o localStorage.

Después de eso, el cliente traerá JWT cuando interactúe con el servidor. Si se almacena en una cookie, se puede enviar automáticamente, pero no cruzará dominios, por lo que generalmente se coloca en el campo Autorización de encabezado de la solicitud HTTP.

Utilice el formato de la siguiente manera

Authorization: Bearer JWT

Todo el proceso de interacción JWT se muestra en la siguiente figura

Inserte la descripción de la imagen aquí

4. Ejemplos

Este ejemplo solo proporciona Java para implementar la firma y verificación JWT, y el uso de la transmisión http se agregará más adelante.

El paquete jar al que pom.xml necesita hacer referencia

<dependency>
      <groupId>com.auth0</groupId>
      <artifactId>java-jwt</artifactId>
      <version>3.10.0</version>
    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.10.2</version>
    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.10.2</version>
    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.10.2</version>
    </dependency>

Clase de herramienta TokenUtil.java

package token;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class TokenUtil {
    
    

    //token过期时长30分钟
    private static final long EXPIRE_TIME = 30 * 60 * 1000;
    //token私钥
    private static final String TOKEN_SECRET = "abcdefg";

    public static String sign(String userName, String password) {
    
    

        String signData = "";
        //过期时间
        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        //私钥及加密算法
        Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
        //设置头信息
        Map<String, Object> header = new HashMap();
        header.put("typ", "JWT");
        header.put("alg", "HS256");

        signData = JWT.create()
                .withHeader(header)
                .withClaim("userName", userName)
                .withClaim("password", password)
                .withExpiresAt(date)
                .sign(algorithm);

        return signData;
    }

    /**
     * @Description token解码校验
     * @param token
     * @return
     * @Create 2020-03-03 by jjy
     */
    public static boolean verfiy(String token) {
    
    

        try {
    
    
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            JWTVerifier jwtVerifier = JWT.require(algorithm).build();
            DecodedJWT decodedJWT = jwtVerifier.verify(token);
            String userName = decodedJWT.getClaim("userName").asString();
            String password = decodedJWT.getClaim("password").asString();
            if(!Test.USERNAME.equals(userName) || !Test.PASSWORD.equals(password)) {
    
    
                return false;
            }
            if(new Date().getTime() > decodedJWT.getExpiresAt().getTime()){
    
    
                return false;
            }
            
        } catch (Exception e) {
    
    
            return false;
        }

        return true;
    }
}

Clase de prueba Test.java

package token;

public class Test {
    
    

    public static final String USERNAME = "user";
    public static final String PASSWORD = "11111111";

    public static void main(String[] args) {
    
    
        String token = TokenUtil.sign(USERNAME, PASSWORD);

        System.out.println("加密后的token为:" + token);

        boolean flag = TokenUtil.verfiy(token);

        if(flag){
    
    
            System.out.println("校验成功");
        } else {
    
    
            System.out.println("校验失败");
        }
    }
}

Los resultados son los siguientes

Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_43611145/article/details/104649851
Recomendado
Clasificación