Based JWT (JSON Web Token) of the authentication token

Encounter is the edge , passing a point of praise ^. ^


Source: https: //github.com/yulc-coding/java-note/tree/master/jwt

Introduction

JWT is a communication between the two sides for the safe delivery of concise information, URL security statements Statement norms, often used in cross-domain authentication. Because there is a digital signature, and thus serves as the anti-falsification

Traditional session mode

Compared with the traditional authentication session, the session is usually saved on the server, the server needs to maintain. And in the case of a server cluster or request services across domains, we need to share the session, so that each server can read the session, such as the session persistence, increasing overhead.

jwt token mode

After the user logs on to the server generates a data token back to the client
each time the client initiates the request token to bring
the server verify the token verification token acquires

format

  • Header header information
{
  "alg""Algorithm  加密方法:HS256",
  "cty""Content Type ",
  "typ""Type" ,
  "kid""Key Id"
 }
复制代码
  • Payload carrier information: packet placed here
{
  "iss""Issuer JWT的签发者",
  "aud""Audience 接收JWT的一方",
  "sub""Subject JWT的主题",
  "exp""Expiration Time JWT的过期时间",
  "nbf""Not Before 在xxx之间,该JWT都是可用的",
  "iat""Issued At 该JWT签发的时间",
  "jti""JWT ID JWT的唯一身份标识",
  "xxx""自定义属性"
}
复制代码
  • Signature signature information = encryption algorithm (header + "." + Payload, key)

  • TOKEN

base64(Header).base64(Payload).Signature
复制代码

Code

pom

    <!-- JWT 支持-->
    <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>java-jwt</artifactId>
        <version>3.8.3</version>
    </dependency>

    <!-- 很好用的一个工具类包 这里用来处理json和AES加密-->
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.0.3</version>
    </dependency>
复制代码

Create a token

You can pass a public statement of fields, you can also pass custom fields

   /**
     * 创建token
     *
     * @param json 需要放入token的参数,多个参数可以封装成json或者map
     * @return token
     */

    public static String createToken(JSONObject json) {
        try {
            // 加密方式
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            return JWT.create()
                    .withSubject(json.toString())
                    .withIssuer("ylc")
                    // 设置过期时间为1分钟后
                    .withExpiresAt(DateUtil.offsetMinute(new Date(), 1))
                    .withClaim("customString""自定义参数")
                    .withArrayClaim("customArray"new Integer[]{123})
                    .sign(algorithm);
        } catch (JWTCreationException exception) {
            //Invalid Signing configuration / Couldn't convert Claims.
            System.out.println(exception.getMessage());
            return null;
        }
    }
复制代码

token verification

Comprising:
Format Checksum: header.payload.signature
encryption checksum: ALG Header value of
signature information Signature verification, to prevent tampering with the data
carrier in the Payload field validation public statement, such as correction iss, jti, exp expiration time test

    /**
     * 校验token 合法性
     *
     * @param token to verify.
     */

    public static boolean verifyToke(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm)
                    // 验证签发人是否相同
                    .withIssuer("ylc")
                    .build();
            /*
             * 校验:
             * 格式校验:header.payload.signature
             * 加密方式校验 Header中的alg
             * 签名信息校验,防串改
             * 载体Payload 中公有声明字段校验
             */

            verifier.verify(token);
            return true;
        } catch (JWTVerificationException exception) {
            //Invalid signature/claims
            System.out.println(exception.getMessage());
            return false;
        }
    }
复制代码

Parsing token

可以通过jwt.getClaims() 获取所有声明字段
也可以通过 jwt.getClaim(name) 获取指定名称的声明字段

/**
 * 解析token
 *
 * @param token to decode.
 */

public static void decodeToken(String token{
    try {
        DecodedJWT jwt = JWT.decode(token);
        Map<String, Claim> claims = jwt.getClaims();
        Claim customStringClaim = claims.get("customString");
        Claim customArrayClaim = claims.get("customArray");

        String issuer = jwt.getIssuer();
        String subject = jwt.getSubject();

        System.out.println(customStringClaim.asString());
        System.out.println(Arrays.toString(customArrayClaim.asArray(Integer.class)));
        System.out.println(issuer);
        System.out.println(JSONUtil.parseObj(subject));

    } catch (JWTDecodeException exception) {
        //Invalid token
        System.out.println(exception.getMessage());
    }
}
复制代码

缺点

  • 默认生成的token不加密,别人可以解析token获取到其中的数据,如果要传递敏感信息,可以先将信息加密后再放入token,或者将生成的token进行加密
  • 每次延长token有效期,会从新生成一个token,需要前端替换原有的token
  • 由于服务器不保存 session状态,因此无法在使用过程中废止某个token,或者更改 token的权限。也就是说,一旦JWT签发了,在到期之前就会始终有效,需要在服务端设置相应的业务逻辑去处理。

Guess you like

Origin juejin.im/post/5ddf7f5ff265da05df4fbd1f