Explicação detalhada da autenticação de token baseada em JWT (implementação Java)

Explicação detalhada da autenticação de token baseada em JWT (implementação Java)

Dicas antes de visualizar:

A versão IDEA usada neste artigo é 2019.1 final, e a versão JDK é 1.8.0_141.

1. Introdução

Na autenticação de identidade de computador, significa token (temporário). O token é realmente mais popular e pode ser chamado de código secreto. Antes de alguma transmissão de dados, o código secreto deve ser verificado primeiro. Diferentes códigos secretos são autorizados para diferentes operações de dados.

2.JWT

JSON Web Token, JSON Web token, nosso exemplo a seguir também é baseado na autenticação de token implementada por JWT, o seguinte é uma string JWT completa

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODMyOTQxNzEsInVzZXJOYW1lIjoidXNlciIsInBhc3N3b3JkIjoiMTExMTExMTEifQ.t6JLktclylpt2s5T_B1KDxYCJALr-fbZsy1J_YT57Jk

É composto por três partes: cabeçalho, carga útil e assinatura

2.1 cabeçalho

Consiste em duas partes

  1. O tipo de declaração é JWT.

  2. Declare o algoritmo de criptografia, use HMAC SHA256

A parte do cabeçalho JWT é um objeto JSON, conforme mostrado abaixo

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

Criptografe-o com Base64 e o JWT constitui a primeira parte.

2.2 carga útil

A parte da carga útil é a parte principal do conteúdo do JWT e também é um objeto JSON, composto de três partes

  1. Declaração registrada na norma

  2. Declaração pública

  3. Declaração privada

A declaração registrada no padrão fornece sete campos padrão.

  1. iss: emissor

  2. exp: tempo de expiração

  3. sub: Assunto

  4. aud: usuário

  5. nbf: Não disponível antes

  6. iat: hora de lançamento

  7. jti: O ID do JWT é usado para identificar o JWT

Declaração pública

A declaração pública pode adicionar qualquer informação, geralmente adicionando informações relacionadas ao usuário ou outras informações necessárias exigidas pela empresa (informações confidenciais não são recomendadas).

Declaração privada

Uma declaração privada é uma declaração definida em conjunto pelo provedor e pelo consumidor (informações confidenciais não são recomendadas).

O exemplo a seguir é um exemplo de carga útil

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

Criptografe-o com Base64 para formar a segunda parte do JWT.

Nota: JWT não é criptografado por padrão e qualquer pessoa pode interpretar seu conteúdo, portanto, não construa campos de informações privadas e armazene informações confidenciais para evitar vazamento de informações.

2.3 assinatura

A parte do hash da assinatura serve para assinar as duas partes dos dados acima e gerar um hash por meio do algoritmo especificado para garantir que os dados não sejam violados. Consiste em três partes:

  1. cabeçalho (criptografado por Base64)

  2. carga útil (criptografado em Base64)

  3. segredo

O servidor precisa de uma chave secreta, que é armazenada apenas no servidor e não pode ser divulgada aos usuários. Em seguida, use o algoritmo de assinatura especificado no cabeçalho (HMAC SHA256 por padrão) para gerar uma assinatura de acordo com a seguinte fórmula.

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

Depois que o hash de assinatura é calculado, as três partes do cabeçalho JWT, carga útil e hash de assinatura são combinadas em uma string e cada parte é separada por "." Para formar o objeto JWT inteiro.

3. Use

O cliente recebe o JWT retornado pelo servidor e o armazena em Cookie ou localStorage.

Depois disso, o cliente trará o JWT ao interagir com o servidor. Se estiver armazenado em um Cookie, pode ser enviado automaticamente, mas não cruzará domínios, portanto, geralmente é colocado no campo Autorização de cabeçalho da solicitação HTTP.

Use o formato a seguir

Authorization: Bearer JWT

Todo o processo de interação do JWT é mostrado na figura abaixo

Insira a descrição da imagem aqui

4. Exemplos

Este exemplo fornece apenas Java para implementar a assinatura e verificação JWT, e o uso de transmissão http será adicionado posteriormente.

O pacote jar que pom.xml precisa fazer referência

<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>

Classe de ferramenta 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;
    }
}

Classe de teste 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("校验失败");
        }
    }
}

Os resultados são os seguintes

Insira a descrição da imagem aqui

Acho que você gosta

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