Young87

当前位置:首页 >个人收藏

一看就懂:JWT 的自述

【1】自我介绍

大家好,我是JWT,但这是我的小名,我的全名叫做 JSON Web Token。

其实,从我的名字中大家可以看出,我通常被开发大大们拿来做 Web请求的 Token 使用。

 

【2】我的出生背景

在没有我出生之前,开发大大们在做 Web 项目的时候,通常是前后端一起写,然后将用户的数据(比如:userId)等信息存放在 session 里,这样用户每次发送请求过来,后端直接可以从 session 里取出 userId,从而知道是哪个用户发的请求了,从而进行该用户的相关操作。

但随着科学的发展,社会的进步,前后端分离的写法越来越多。 session 大叔也逐渐不适应这个时代的潮流而被 out 出局了。

那么该怎么解决呢?聪明的开发大大们就想到在用户登录的时候对 userId 进行加密得到一个字符串,再把这个字符串返给前端,就相当于一个凭证(token),这样前端每次请求都带上这个字符串,后端通过解密得到 userId,这样也是可以的。

 

但有的开发大大技术不到家,加密的技术不够精明,导致 token 不断被破解,于是就出现了很多安全事故。

所以,行业里就迫切需要一个通用且安全的前后端 token 加密方式,于是,当!当!当!我就诞生啦!

我就是集万千开发大大宠爱于一身的前后端分离 Token 加密技术 JWT !!

 

【3】我的结构组成

大家可以先脸熟我下,我的长相大致如下:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsImlzcyI6Inp5cSIsInVhY2MiOiI1MTE2MDIxMCIsInBpZCI6NCwiZXhwIjoxNjAzMTc3Njc0LCJpYXQiOjE2MDMwOTEyNzR9.BsuCzF5Xd9MfV8vXxK-Lins4kO5dIuAF3a0PHv7hIK4

大家看到没有,我的身上有两个点,将整个身体分成了3个部分。

第 1 部分:这是我的头,解密这部分后,可以得到加密的方式和类型。

第 2 部分:这是我的身子,解密这部分后,就能获得开发大大们的数据。

第 3 部分:这是我的尾巴,这一部分是加密凭证,是对头和身子再次加密,所以数据很安全。

这三个就构成一个完整的我(JWT)结构。

 

【4】实战经历

说了这么多,项目中到底是怎么用我的呢?下面就以我当 Token 工作时的全过程给大家讲述下。

(1)首先你需要导入我的 maven 依赖。

<!-- JWT -->
<dependency>
	<groupId>com.auth0</groupId>
	<artifactId>java-jwt</artifactId>
	<version>3.4.0</version>
</dependency>

(2)然后我加密写法为(比如这里我去加密userId):

写个 main 方法测试下吧:

(3)我的解密写法为:

继续测试:可以看到,数据已经成功被解密出来啦!

【5】 我的工具类

下面是我的完整工具类(作者大大亲手写的哦)

package com.zyq.tools;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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


/**
 * JWT 工具类
 * @author zyq
 * @since 2020年10月22日
 */
public class JwtUtil {

    /** 日志 */
    private  static final Logger log = LoggerFactory.getLogger(JwtUtil.class); 
    /** 密钥 */
    private static final String SECRET_KEY = "0123456789_0123456789_0123456789";
    /** 加密方式 */
    private static final Algorithm ALGORITHM = Algorithm.HMAC256(SECRET_KEY);
    /** 签发人 */
    private static final String ISSUER = "zyq";
    /** 过期时间:1天(单位:毫秒) */
    private static final long TOKEN_EXPIRE_TIME =  24 * 60 * 60 * 1000;
    /** 加密数据(键) */
    private static final String USER_ID = "userId";
    
    /**
     *  测试主方法
     */
    public static void main(String[] args) {
        String token = getToken("123456789");
        System.out.println("加密后的 token 为:" + token);
        String userId = decodedToken(token);
        System.out.println("解密后的 userId 为:" + userId);
    }
    
    /**
     * 加密 token
     */
    public static String getToken(String userId) {
        // 签发时间
        Date now = new Date();
        return JWT.create()
                // 签发人
                .withIssuer(ISSUER)
                // 签发时间
                .withIssuedAt(now)
                // 过期时间
                .withExpiresAt(new Date(now.getTime() + TOKEN_EXPIRE_TIME))
                .withClaim(USER_ID, userId)
                .sign(ALGORITHM);
    }

    /**
     * 解析 token
     */
    public static String decodedToken(String token) {
        DecodedJWT jwt;
        try {
            jwt = JWT.decode(token);
        } catch (Exception e) {
            log.warn("异常token:{}", token);
            return null;
        }
        if (new Date().getTime() > jwt.getExpiresAt().getTime()) {
            log.warn("token 已过期:{}", token);
            return null;
        }
        return jwt.getClaim(USER_ID).asString();
    }  

}

 

 好了,我的自述差不多就到这里了,你现在认识我了吗?青山不改,绿水长流,咱们后会有期!拜拜!

 

除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog

上一篇: MySQL数据中有很多换行符和回车符!!该咋办?

下一篇: 如何写出让 CPU 跑得更快的代码?

精华推荐