JWT令牌

前言:涉及知识范围(学习内容)

非框架部分:map,Iterator

框架部分:ssm,jwt

Java迭代器(Iterator)是 Java 集合框架中的一种机制,是一种用于遍历集合(如列表、集合和映射等)的接口。

它提供了一种统一的方式来访问集合中的元素

map(映射):用于存储键值对,常见的有哈希表map与黑红树map

Map<String, Integer> hashMap = new HashMap<>();
Map<String, Integer> treeMap = new TreeMap<>();

|----|-----------------|-------------------|
| | HashMap | TreeMap |
| 特性 | 基于哈希表实现的键值对存储结构 | 基于红黑树实现的有序键值对存储结构 |
| 优点 | 高效的查找、插入和删除操作 | 有序,支持按照键的顺序遍历 |
| 缺点 | 无序,不保证顺序插 | 插入和删除相对较慢 |

++在不深入的情况下,暂时先把它当成一个特殊的对象(数组)++

提到键值对,那么第一时间应该会想到数据库和引用数据类型:对象,数组

提到映射,在使用mybtis的时候,我们涉及到了这一概念,它的本质是一种元素与元素之间的关系

具体点:一对一,一对二,一对三的关系,无法逆转(单向)

例子:你能直接通过值去找到数组和对象的键吗?很显然,不能,要通过一些手段才可以找到


JWT: JSON Web Token

三部分组成:算法和令牌类型,数据,验证签名

在生成jwt的时候,就是按照这三种形式去自定义一个jwt令牌

maven依赖

复制代码
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>4.3.0</version>
</dependency>

依赖导入完后,开始进入正片,那么前面的内容是干什么的?大致了解一下就好了

我们会使用到JWT这个类

java 复制代码
public class JWT {
    private final JWTParser parser = new JWTParser();

    public JWT() {
    }

    public DecodedJWT decodeJwt(String token) throws JWTDecodeException {
        return new JWTDecoder(this.parser, token);
    }

    public static DecodedJWT decode(String token) throws JWTDecodeException {
        return new JWTDecoder(token);
    }

    public static Verification require(Algorithm algorithm) {
        return JWTVerifier.init(algorithm);
    }

    public static JWTCreator.Builder create() {
        return JWTCreator.init();
    }
}

我们将使用到JWT类中的Builder类型 create方法(函数)和Verification类型 reqiore方法(函数)

前者返回:JWTCreator.init =》中文翻译为JWT生成器

后者返回:JWTVerifier.init(algorithm),翻译 =》JWT验证器(参数为验证签名)

先从生成器开始,它方法类型是一个JWTCreator.Builder对象,并返回初始化器,看看源码

init(),直接 new 了一个Builder类

也就是说Builder是核心中的中心,搞懂Builder就是搞懂JWT生成令牌

在接下来的使用将会一步一步看源码

知道了是生成器是哪个方法,我们直接用就好了

java 复制代码
@SpringBootTest
@Configuration
class CodeRomaBackendApplicationTests {

    @Test
    public void JWT(){

        JWT.create()

    }

}

这样就完成了第一步

按一下.会有很多方法

这里我们回到builder的源码


JWT由三部分组成:算法和令牌类型,数据,验证签名 == header,payload,sign

java 复制代码
        private final Map<String, Object> payloadClaims = new HashMap();
        private final Map<String, Object> headerClaims = new HashMap();

在源码中标有这两个变量,那么现在应该可以看懂了吧

一个用来存储header的键值对

另一个用来存储payload的键值对

键值对,键对应性,值对应名,口头说很抽象,还是直接上代码容易点

提一嘴,map.put是存入,类似于实体类中的set方法

java 复制代码
@SpringBootTest
@Configuration
class CodeRomaBackendApplicationTests {

    public void JWT(){
        // JWT头部分信息【Header】
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "HS256");//性为alg,名为HS256
        header.put("typ", "JWT");//性为typ,名为JWT

        // 载核【Payload】
        Map<String, Object> payload = new HashMap<>();
        payload.put("sub", "1234567890");//性为sub,名为123456789
        payload.put("name","John Doe");//性为name,名为John Doe
        payload.put("admin",true);//性为admin,名为true

        JWT.create()
                .withHeader(header)//头部
                .withPayload(payload)//负载

    }
}

定义了header和payload信息,有了头和负载,现在就差签名了

第一个对应的header的源码

java 复制代码
public Builder withHeader(Map<String, Object> headerClaims) {
            if (headerClaims == null) {
                return this;
            } else {
                Iterator var2 = headerClaims.entrySet().iterator();

                while(var2.hasNext()) {
                    Map.Entry<String, Object> entry = (Map.Entry)var2.next();
                    if (entry.getValue() == null) {
                        this.headerClaims.remove(entry.getKey());
                    } else {
                        this.headerClaims.put((String)entry.getKey(), entry.getValue());
                    }
                }

                return this;
            }
        }

第二个对应的payload的源码

java 复制代码
public Builder withPayload(Map<String, ?> payloadClaims) throws IllegalArgumentException {
            if (payloadClaims == null) {
                return this;
            } else if (!this.validatePayload(payloadClaims)) {
                throw new IllegalArgumentException("Claim values must only be of types Map, List, Boolean, Integer, Long, Double, String, Date, Instant, and Null");
            } else {
                Iterator var2 = payloadClaims.entrySet().iterator();

                while(var2.hasNext()) {
                    Map.Entry<String, ?> entry = (Map.Entry)var2.next();
                    this.addClaim((String)entry.getKey(), entry.getValue());
                }

                return this;
            }
        }

前面的if条件判断语句一般情况下,你只要有内容都是不会有报错的

重点是循环里面的内容,map集合里有一个方法叫getkey和getvalue

复制代码
Map.Entry是map里的内部接口,在那之前entrySet().iterator();很关键
  1. getKey():返回与此条目相关联的键。
  2. getValue():返回与此条目相关联的值。

将我们存入的map通过循环取出来,使用,用sign结束

java 复制代码
public String sign(Algorithm algorithm) throws IllegalArgumentException, JWTCreationException {
            if (algorithm == null) {
                throw new IllegalArgumentException("The Algorithm cannot be null.");
            } else {
                this.headerClaims.put("alg", algorithm.getName());
                if (!this.headerClaims.containsKey("typ")) {
                    this.headerClaims.put("typ", "JWT");
                }

                String signingKeyId = algorithm.getSigningKeyId();
                if (signingKeyId != null) {
                    this.withKeyId(signingKeyId);
                }

                return (new JWTCreator(algorithm, this.headerClaims, this.payloadClaims)).sign();
            }
        }

哎,它返回一个this.headerClaims是不是意味着header有另一个方法实现

this我们知道,他是隐性调用,那么意味着algorithm里面有这个headerClaims参数

修改一下代码

java 复制代码
    @Test
    public void JWT(){
        Algorithm algorithm = Algorithm.HMAC256("secret");

        // 载核【Payload】
        Map<String, Object> payload = new HashMap<>();
        payload.put("sub", "1234567890");//性为sub,名为123456789
        payload.put("name","John Doe");//性为name,名为John Doe
        payload.put("admin",true);//性为admin,名为true

        String sign = JWT.create()
                .withPayload(payload)//负载
                .sign(algorithm);

        System.out.println(sign);
    }

成果打印出来了!!!

相关推荐
笃励18 分钟前
Java面试题二
java·开发语言·python
ん贤20 分钟前
贪心算法.
算法·贪心算法
jyan_敬言26 分钟前
【Linux】Linux命令与操作详解(一)文件管理(文件命令)、用户与用户组管理(创建、删除用户/组)
linux·运维·服务器·c语言·开发语言·汇编·c++
cndes28 分钟前
大数据算法的思维
大数据·算法·支持向量机
FL162386312930 分钟前
[C#]C# winform部署yolov11-pose姿态估计onnx模型
开发语言·yolo·c#
易雪寒36 分钟前
IDEA在git提交时添加忽略文件
java·git·intellij-idea
笑非不退41 分钟前
C++ 异步编程 并发编程技术
开发语言·c++
打码人的日常分享1 小时前
企业人力资源管理,人事档案管理,绩效考核,五险一金,招聘培训,薪酬管理一体化管理系统(源码)
java·数据库·python·需求分析·规格说明书
27669582921 小时前
京东e卡滑块 分析
java·javascript·python·node.js·go·滑块·京东
爱写代码的刚子1 小时前
C++知识总结
java·开发语言·c++