Spring Boot中使用token:jwt

2023-11-02

token由3部分组成:Header,Payload,Signature。

其中Header记录了签名算法和token 的类型。

Payload是以明文存储的一些信息,包括用户自定义信息。

Signature是使用签名算法,对Payload结合服务端才知道的私钥进行签名后得出的结果。

服务端对这3部分使用base64编码,然后以.号分隔,就得到了token字符串,格式为:

xxxxxx.yyyyyy.zzzzzz

每次前端进行请求时,带上这个token字符串。当服务端收到请求后,就会对Payload计算签名,然后与token中的Signature进行比较,若一致,则通过。

逻辑简单,完全可以自己写一个token类来实现以上功能。

Spring Boot中提供了一个第三方的token库,叫jwt。

 

  1. 在pom.xml中引入依赖:
<!-- JWT Json Web Token 依赖 -->
<dependency>
   <groupId>io.jsonwebtoken</groupId>
   <artifactId>jjwt</artifactId>
   <version>0.7.0</version>
</dependency>
  1. 生成token:
public String getAccessToken() {
    JwtBuilder jwtBuilder = Jwts.builder();

    long nowMillis = System.currentTimeMillis();
    // 7个官方Payload字段
    jwtBuilder.setId("1.0"); // 编号/版本
    jwtBuilder.setIssuer("ISSUER"); // 发行人
    jwtBuilder.setSubject("SUBJECT"); // 主题
    jwtBuilder.setAudience("AUDIENCE"); // 受众
    jwtBuilder.setIssuedAt(new Date(nowMillis)); // 签发时间
    jwtBuilder.setNotBefore(new Date(nowMillis)); // 生效时间
    jwtBuilder.setExpiration(new Date(nowMillis + (60 * 60 * 1000))); // 失效时间

    // 用户自定义字段
    jwtBuilder.claim("id", "AXDBDCD");
    jwtBuilder.claim("name", "testname");
    jwtBuilder.claim("value", "123456");
    
    // 定义私钥
    String HS256KEY = "xxxxxx";
    // 签名算法
    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
    // 计算签名key值
    Key signingKey = new SecretKeySpec(Base64.decodeBase64(HS256KEY), signatureAlgorithm.getJcaName());

    // 进行签名
    jwtBuilder.signWith(signatureAlgorithm, signingKey);

    // 获取token字符串
    String tokenString = jwtBuilder.compact();

    return tokenString;
}

注意:

  • 要先为jwtBuilder设置claims,然后再调用jwtBuilderset接口来设置7个官方payload字段。这是因为jwtBuilder是将7payload字段存储在claims中的。若先设置了payload,再设置claims,会将已设置的payload覆盖掉。
  • payload字段中:id通常设为版本号;issuer是发行人,通常设为公司名;subject是主题,通常设为工程名;audience是受众,通常设为获取token 的接口名。一般来说,audience多被设为” login”,也就是登录。
  • 7个官方payload字段中的3个时间:签发时间(issued at),生效时间(not before),失效时间(expiration)。3个时间使用的单位是秒。调用jwtBuilderset接口来设置这3个时间时,只需要传入Date()型数据即可,JwbBuilder会自动将其转换为秒存储在claims的相应字段里。详见附录。
  1. 解析token:
public boolean isTokenValid(String token) {
    try {
        Claims claims = Jwts.parser().setSigningKey(signingKey).parseClaimsJws(token.trim()).getBody();
        Date date = claims.getExpiration();
        return new Date().before(date);
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

将token字符串解析为Jws对象,然后获取claims,这样就能拿到claims中存储的各个字段。然后自行判断即可。其中解析用的signingKey与2中生成的signingKey是同一个。

由于(当前解析的时间<生效时间)或(当前解析的时间>失效时间)均会抛出异常,所以需要对异常进行捕获,返回false给前端,表示token已失效。

 

 

附录

  1. claims的设置

JwtBuilder允许用户自定义claims,并提供了3个相关函数:

JwtBuilder setClaims(Claims var1);
JwtBuilder setClaims(Map<String, Object> var1);
JwtBuilder claim(String var1, Object var2);

其中:

  • 两个setClaims会将之前已存在的claims覆盖掉。
  • claim会将新的值push给当前claims。

JwtBuilder将7个官方payload字段也存储在claims中。也就是说,用户自定义的字段和官方的payload字段是存放在一起的。

因此,若已经为JwtBuilder设置了claims字段,则不能再调用setClaims(),否则已设置的会被覆盖。推荐使用claim()函数。

JwtBuilder提供了7个set函数来设置7个官方payload字段。以setExpiration()为例。

·若还没有调用JwtBuilder的setClaims(),则调用setExpiration(),会先为JwtBuilder添加一个空的claims,然后将expiration设置进去。

·若已经调用了JwtBuilder的setClaims(),则调用setExpiration(),会将expiration的值push到已存在的claims中。

  1. not before与expiration

7个官方payload字段中,有3个时间:

·issue at:签发时间

·not before:生效时间

·expiration:失效时间

当Jwts对token字符串进行解析时,若存在not before和expiration,则会进行判断:

当前解析的时间必须>=not before

当前解析的时间必须<=expiration

否则会抛出异常。所以解析时需要对异常进行捕获处理。

若这2个时间都没有进行设置,则不会进行判断。

然而,其流程是:

JwtBuilder调用setNotBefore()来设置时间→生成token返回给用户→用户请求→对请求的token进行解析。

其中:

  • setNotBefore()来设置时间时,将时间转换为秒,是一个long型的数据,存储到claims中。
  • 解析时,将claims中的秒取出来,转成Date型数据,然后与当前时间的Date比较,来判断是否抛出异常。

因此:

jwtBuilder.setNotBefore(new Date());
jwtBuilder.claim("nbf", new Date().getTime()/1000);

效果是相同的。

其中7个字段名(例如"nbf")定义在Claims接口中(例如Claims.NOT_BEFORE)。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Boot中使用token:jwt 的相关文章

随机推荐

  • C 标准库 - 《stdio.h》

    原文链接 https www runoob com cprogramming c standard library stdio h html 简介 stdio h 头文件定义了三个变量类型 一些宏和各种函数来执行输入和输出 库变量 下面是头
  • 前端页面间数据传递常用的几种方式

    1 常用方式 url页面路径携带参数传递 localStorage方式传递 sessionStorage方式传递 cookie的方式传递 2 方式对比 url字节限制可以参考这一篇文章 HTTP中的URL长度限制 其中cookie的setC
  • 开关电源的时钟倍频 辐射发射超标RE+ 噪声源+干扰原因

    1 收藏 史上最全开关电源传导与辐射超标整改方案 医疗设备低频30 50Mhz超标 2 https bbs elecfans com m jishu 941580 1 1 html 3 辐射噪声的产生机理 知乎 1 电流源 噪声源 2 天线
  • 【华为OD机试】叠积木(C++ Python Java)2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 语言限定 C clang11 C clang 11 Pascal fpc 3 0 2 Java jav
  • 傅里叶变换快速入门

    网上关于傅里叶变换的解释特别多 但大部分都比较偏理论 导致我看来N多教程也还是懵懵懂懂 在某本书 信号完整性分析 中看到一句震耳发聩的话 每个工程师都应该亲自动手计算一遍傅里叶变换 我知道很多工具可以直接给出傅里叶变换结果 但不清不楚一直是
  • 修改UGF官方的starForce为自己所用

    第一步 修改Launcher的名字 比如我这里是修改成SpaceShoot 第二步修改命名空间名字 重新命名为SpaceShoot 第三步 重新设置Launcher场景中丢失的脚本 Builtin下JsonLite Localization
  • 设计模式-工厂方法模式

    文章目录 前言 工厂方法模式概述 使用场景 工厂方法模式优缺点 Java代码示例 前言 当我们面临需要创建不同类型对象的需求时 通常会使用工厂方法模式 工厂方法模式是一种创建型设计模式 它提供了一种将对象的创建与使用分离的方法 允许我们在不
  • VMware Workstation安装

    VMware Workstation安装 1 安装步骤 双击运行安装包程序 接受许可证协议 关键不接受不让安装啊 选择安装位置 建议非中文无空格 增强型键盘驱动程序可选 按照自身使用习惯勾选产品更新和客户体验提升计划 快捷方式 开始安装 稍
  • MD5加密

    1 md5是什么 md信息摘要算法 一种被广泛使用的密码散列函数 2 md5的特征 一 长度固定 任意长度的数据都会输出长度相等的md5值 二 不可逆 三 对原密码进行改动改变成一个字节输出数据 四 很少碰到两个不同的数据产生相同的md5值
  • 算法该不该刷?如何高效刷算法?

    一 算法该不该刷 最近有小伙伴向我咨询一个问题 就是算法该不该刷 该如何刷算法呢 这个问题可谓太大众化了 只要你去某乎 某度搜索一下相关的解答 会有无数种回答 可见这个问题困扰了多少学习计算机的同学们 但不管回答有多少种 总结一句话就是 算
  • 科大奥锐密立根油滴实验数据_密立根油滴实验数据表格

    静态法 平衡法 第1粒油滴数据 序数 U V t g s v g m s 1 q i C n i 个 e C 10 19 u e e 0 1 235 9 98 1 50E 04 1 12E 18 7 1 61 0 62 2 235 9 88
  • chatglm-6b模型在windows的详细安装教程

    1 先是看了github的文章 如果打不开这篇文章 可能需要科学上网 即访问外网的VPN https github com THUDM ChatGLM 6B 2 准备 台式机 GPU是8G 关于是否可以在笔记本运行 我后面测试下 等我下一篇
  • 什么是频谱仪的RBW带宽和VBW带宽

    1 RBW Resolution Bandwidth 代表两个不同频率的信号能够被清楚的分辨出来的最低频宽差异 两个不同频率的信号频宽如低于频谱分析仪的RBW 此时该两信号将重叠 难以分辨 RBW 分辨率带宽 有人也叫参考带宽 表示测试的是
  • 在laravel中合并路由_一些实用的 Laravel 小技巧

    Laravel 中一些常用的小技巧 说不定你就用上了 1 侧栏 1 网站一般都有侧栏 用来显示分类 标签 热门文章 热门评论啥的 但是这些侧栏都是相对独立的模块 如果在每一个引入侧栏的视图中都单独导入与视图有关的数据的话 未免太冗余了 所以
  • 算法——回溯法(子集、全排列、皇后问题)

    参考 http www cnblogs com wuyuegb2312 p 3273337 html intro 参考 算法竞赛入门经典 P120 1 定义 回溯算法也叫试探法 它是一种系统地搜索问题的解的方法 回溯算法的基本思想是 从一条
  • IDA宏定义

    This file contains definitions used by the Hex Rays decompiler output It has type definitions and convenience macros to
  • 机器学习中的 K-均值聚类算法及其优缺点。

    K 均值聚类算法是一种常见的无监督学习算法 它可以将数据集分成 K 个簇 每个簇内部的数据点尽可能相似 而不同簇之间的数据点应尽可能不同 下面详细讲解 K 均值聚类算法的优缺点 优点 简单易用 K 均值聚类算法是一种简单易懂的算法 容易理解
  • String index out of range错误与解决方法

    在做算法题时遇到了报错 原因是字符串的索引越界 查看自己的代码 原来int的类型范围越界 int的范围 2147483648 2147483647 long的范围 9223372036854775808 922337203685477580
  • golang-nil切片和空切片

    package main import fmt func main var a int b make int 0 if a nil fmt Println a is nil else fmt Println a is not nil if
  • Spring Boot中使用token:jwt

    token由3部分组成 Header Payload Signature 其中Header记录了签名算法和token 的类型 Payload是以明文存储的一些信息 包括用户自定义信息 Signature是使用签名算法 对Payload结合服