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);
    }

成果打印出来了!!!

相关推荐
半摆烂日常32 分钟前
手机表单的左滑操作:触摸事件的处理细节
大数据·开发语言·人工智能·智能手机·https·c#
星夜离尘5643 分钟前
MATLAB滑动RMS如何接报警:窗口未满和缺样不能当成正常
开发语言·matlab
SL_staff1 小时前
周报越厚问题越拖?用结构化执行机制让周报回归决策价值
java·spring cloud·开源
开开心心就好1 小时前
白天晚上自动调蓝光,护眼工具亮度可调
服务器·开发语言·算法·pdf·ocr·intellij-idea·idea
张张123y1 小时前
后端第十一课:RAG 落地实战(从 0 到 1 接上私有知识库,并设计一个好用的 RAG)
开发语言·人工智能·python·机器学习·fastapi·rag
梅梅绵绵冰1 小时前
JVM虚拟机
java·开发语言·jvm
golang学习记1 小时前
Python vs Go:2026年到底该怎么选
java·vscode·python·golang·pycharm·goland
Shaoshing1 小时前
消息顺序
java·开发语言
云水初2 小时前
【项目篇】基于LanGraph的自动处理客服邮件的 Agent汇总
开发语言·笔记·python·学习·fastapi·langgraph
茉莉玫瑰花茶2 小时前
GO [ 内存与变量逃逸分析 ]
开发语言·后端·golang