JWT生成令牌

实现步骤

  1. 引入JWT包
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.12.3</version>
</dependency>
  1. 定义令牌类型枚举
package com.angel.ocean.token.constant;public enum TokenTypeEnum {ACCESS_TOKEN(0),REFRESH_TOKEN(1);private int code;TokenTypeEnum(int code) {this.code = code;}public int getCode() {return code;}
}
  1. 定义令牌数据模型

令牌信息类 TokenInfo

package com.angel.ocean.token.model;import lombok.Data;@Data
public class TokenInfo {/*** 令牌*/private String accessToken;/*** 令牌过期时间,秒级时间戳*/private Long accessTokenExpireIn;/*** 刷新令牌*/private String refreshToken;/*** 刷新令牌过期时间,秒级时间戳*/private Long refreshTokenExpireIn;}

用户信息类 UserInfo

package com.angel.ocean.token.model;import lombok.Data;/*** 用户信息*/
@Data
public class UserInfo {private Long uid;private String name;}
  1. 定义生成令牌的工具类

主要包含以下功能:

  • 生成令牌
  • 刷新令牌
  • 获取令牌用户数据
  • 令牌过期校验
package com.angel.ocean.token;import com.angel.ocean.token.constant.TokenTypeEnum;
import com.angel.ocean.token.model.TokenInfo;
import com.angel.ocean.token.model.UserInfo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SecureDigestAlgorithm;
import javax.crypto.SecretKey;
import java.time.Instant;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;public class TokenUtil {/*** 过期时间(单位:秒)*/public static final Integer ACCESS_TOKEN_EXPIRE = 300;/*** 过期时间(单位:秒)*/public static final Integer REFRESH_TOKEN_EXPIRE = 7200;/*** 加密算法*/private final static SecureDigestAlgorithm<SecretKey, SecretKey> ALGORITHM = Jwts.SIG.HS256;/*** 私钥*/private final static String SECRET = "lMN0So4pxpeyPec3ap32Vg7e6JkjEjfT";/*** 秘钥实例*/public static final SecretKey KEY = Keys.hmacShaKeyFor(SECRET.getBytes());/*** jwt签发者*/private final static String JWT_ISS = "Ocean";/*** jwt主题*/private final static String SUBJECT = "Peripherals";/*** 生成令牌* @param userInfo* @return*/public static TokenInfo generateToken(UserInfo userInfo) {Map<String, Object> payload = new HashMap<>();payload.put("name", userInfo.getName());payload.put("uid", userInfo.getUid());payload.put("type", TokenTypeEnum.ACCESS_TOKEN.getCode());Integer accessTokenExpireIn = ACCESS_TOKEN_EXPIRE;String accessToken = generateToken(payload, accessTokenExpireIn);payload.put("type", TokenTypeEnum.REFRESH_TOKEN.getCode());Integer refreshTokenExpireIn = REFRESH_TOKEN_EXPIRE;String refreshToken = generateToken(payload, refreshTokenExpireIn);TokenInfo tokenInfo = new TokenInfo();tokenInfo.setAccessToken(accessToken);tokenInfo.setAccessTokenExpireIn(getTokenExpireIn(accessToken));tokenInfo.setRefreshToken(refreshToken);tokenInfo.setRefreshTokenExpireIn(getTokenExpireIn(refreshToken));return tokenInfo;}/*** 刷新令牌* @param refreshToken* @return*/public static TokenInfo refreshToken(String refreshToken) {UserInfo userInfo = getUserInfoByToken(refreshToken);return generateToken(userInfo);}/*** 获取令牌用户数据* @param token* @return*/public static UserInfo getUserInfoByToken(String token) {final Claims claims = parsePayload(token);UserInfo userInfo = null;if (null != claims) {userInfo = new UserInfo();userInfo.setName(claims.get("name").toString());userInfo.setUid(Long.parseLong(claims.get("uid").toString()));}return userInfo;}/*** 令牌过期校验 true-过期 false-未过期* @param token* @return*/public static Boolean isExpired(String token) {Boolean result = true;final Claims claims = parsePayload(token);if (null != claims) {String exp = claims.get("exp").toString();long diff = Long.parseLong(exp) - System.currentTimeMillis() / 1000;if(diff > 0) {result = false;}}return result;}/*** 获取令牌的过期时间*/private static Long getTokenExpireIn(String token) {Long expireIn = System.currentTimeMillis() / 1000;final Claims claims = parsePayload(token);if (null != claims) {String exp = claims.get("exp").toString();return Long.parseLong(exp);}return expireIn;}/*** 生成令牌*/private static String generateToken(Map<String, Object> payload, Integer expireTime) {Date expireDate = Date.from(Instant.now().plusSeconds(expireTime));return Jwts.builder().header().add("typ", "JWT").add("alg", "HS256").and().claims(payload).id(UUID.randomUUID().toString()).expiration(expireDate).issuedAt(new Date()).subject(SUBJECT).issuer(JWT_ISS).signWith(KEY, ALGORITHM).compact();}/*** 解析令牌claims*/private static Jws<Claims> parseClaim(String token) {return Jwts.parser().verifyWith(KEY).build().parseSignedClaims(token);}/*** 解析令牌header*/private static JwsHeader parseHeader(String token) {return parseClaim(token).getHeader();}/*** 解析令牌payload*/private static Claims parsePayload(String token) {return parseClaim(token).getPayload();}
}

生成令牌样式

{"accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsIm5hbWUiOiJKYWltZSIsInR5cGUiOjAsImp0aSI6IjNjOWFhMDIxLWNkN2MtNDQ1Ni1hMTE1LTYxOWJkOTg3NzI2NCIsImV4cCI6MTcxOTA2MTQwMiwiaWF0IjoxNzE5MDYxMTAyLCJzdWIiOiJQZXJpcGhlcmFscyIsImlzcyI6Ik9jZWFuIn0.Cj_UJfbaWaiSu82ma-C1hd8L1u2_x3RRBHkXK5XFAPA","accessTokenExpireIn": 1719061402,"refreshToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsIm5hbWUiOiJKYWltZSIsInR5cGUiOjEsImp0aSI6IjU4YTVmZDAzLTlkYWYtNDY2ZS05NjMwLTQyNjU5ODZmYTViNiIsImV4cCI6MTcxOTA2ODMwMywiaWF0IjoxNzE5MDYxMTAzLCJzdWIiOiJQZXJpcGhlcmFscyIsImlzcyI6Ik9jZWFuIn0.jegxFBj4t-AJhiWY_OByEs0vtsHBb0d0vjEerVFl85E","refreshTokenExpireIn": 1719068303
}

系统认证流程

  • 用户登录系统,用户有效,生成令牌返回给客户端(Web前端或APP等);
  • 客户端记录令牌信息和刷新令牌信息;
  • 客户端携带令牌(一般放在头信息中)去请求服务器的资源;
  • 服务进行令牌校验,检验通过返回资源信息给客户端,检验失败返回401(鉴权失败)给客户端;
  • 客户端收到401响应码,知道令牌失效了,此时使用刷新令牌去重新获取令牌;
  • 服务校验刷新令牌是否有效,如何有效,重新返回令牌信息给客户端(包含令牌和刷新令牌);
  • 如果刷新令牌校验失败,则返回402(刷新令牌校验失败),此时客户端需要跳转到登录页,用户需要重新登录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/32235.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

go语言进阶实战学习(逐行注释)(1):两协程并发交替打印数字和字母

要求&#xff1a; 并发两协程交替打印数字和字母。一个协程打印数字&#xff0c;一个协程打印字母。 输出&#xff1a; 12AB34CD56EF78GH910IJ1112KL1314MN1516OP1718QR1920ST2122UV2324WX2526YZ2728 思路&#xff1a; 两个 channel 控制两个协程进行交替打印。sync.WaitG…

PyScada(三)后端应用

PyScada 的后端应用 使用后端 要使用后端&#xff0c;请在浏览器中打开http://127.0.0.1 &#xff08;将 127.0.0.1 替换为 PyScada 服务器的 IP 或主机名&#xff09;&#xff0c;然后使用安装过程 中定义的管理员帐户登录 &#xff08;TODO 链接到创建超级用户文档&#xf…

Java基础的重点知识-01

文章目录 开发前言Java语言开发环境入门程序说明常量变量和数据类型数据类型转换运算符方法解析 开发前言 常用DOS命令 Java语言的初学者&#xff0c;学习一些DOS命令&#xff0c;会非常有帮助。DOS是一个早期的操作系统&#xff0c;现在已经被Windows系统取代&#xff0c;对于…

STL——函数对象,谓词

一、函数对象 1.函数对象概念 概念&#xff1a; 重载函数调用操作符的类&#xff0c;其对象常称为函数对象。 函数对象使用重载的()时&#xff0c;行为类似函数调用&#xff0c;也叫仿函数。 本质&#xff1a; 函数对象(仿函数)是一个类&#xff0c;不是一个函数。 2.函数对象…

Vue2动态代理无须重启项目解决方案

1、痛点 如果我们需要使用不同的环境地址的时候&#xff0c;就需要使用命令或者手动修改vue.config.js中配置来重新启动项目。当项目项目越来越大的时候&#xff0c;我们需要很长的时间来启动项目&#xff0c;如此反复&#xff0c;极大影响我们开发进度。 2、寻求解决方案 ● v…

RAG和agent框架选型

langChain llama index autoGen metaGPT

spring使用@PostConstruct踩得坑

情况说明&#xff1a; 在一个抽象类中使用PostConstruct注解方法init用于初始化操作。然后每个实现类在初始化时都会调用PostConstruct注解的init方法执行初始化操作。如下代码&#xff1a; public abstract class AbstractClass {/*** 存放各实例.*/public static final Map&…

git分支及提交规范【AI 文心一言】

Git代码提交规范和分支命名规范是团队协作中非常重要的部分&#xff0c;它们有助于保持代码库的清晰、一致和易于管理。以下是对Git代码提交规范和采用“/”分割的分支命名规范的总结&#xff1a; Git代码提交规范 提交类型&#xff1a; feat: 增加新功能 fix: 修复问题BUG d…

Windows安装多个jdk环境(jdk6+jdk8+jdk17)保姆级

Windows安装多个jdk环境&#xff08;jdk6jdk8jdk17&#xff09;保姆级 背景&#xff1a;新机安装开发环境发现需要找很多文章&#xff0c;&#xff0c;&#xff0c;&#xff0c;这里一篇文章安装所有环境 文章目录 Windows安装多个jdk环境&#xff08;jdk6jdk8jdk17&#xff09…

经典游戏案例:植物大战僵尸

学习目标&#xff1a;植物大战僵尸核心玩法实现 游戏画面 项目结构目录 部分核心代码 using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; using Random UnityEngine.Random;public enum Z…

Django 条件判断模板标签

1&#xff0c;条件判断模板标签 1. 2 {% if %} 标签 {% if variable %}<!-- 如果 variable 为 True&#xff0c;则渲染此处内容 --> {% endif %} 1. 3 {% if %} 与 {% else %} 组合 {% if variable %}<!-- 如果 variable 为 True&#xff0c;则渲染此处内容 -->…

【笔记】git源

报错信息 # git clone https://github.com/paddlepaddle/PaddleCustomDevice Cloning into PaddleCustomDevice... error: RPC failed; curl 16 Error in the HTTP2 framing layer fatal: expected flush after ref listing可选源 由于&#x1f512;&#x1f5fa;&#xff0c…

BFS:解决最短路问题

文章目录 什么是最短路问题&#xff1f;1.迷宫中离入口最近的出口2.最小基因变化3.单词接龙4.为高尔夫比赛砍树总结 什么是最短路问题&#xff1f; 最短路问题是图论中的经典问题&#xff0c;旨在寻找图中两个节点之间的最短路径。常见的最短路算法有多种&#xff0c;这次我们…

【python包安装】手动安装libmr

遇到问题 再导入libmr模块时&#xff0c;导入失败 尝试使用pip install libmr安装&#xff0c;安装失败 查询原因是windows上pip安装找不到库&#xff0c;只能采取手动安装。 解决方法 下载libMR库文件 安装方法可以查看README文档 安装libmr之前需要安装Microsoft C14或…

开启数字新纪元:全球首款开源AI女友,你的私人数字伴侣

在这个数字化飞速发展的时代,人工智能已经不再是科幻小说中的幻想,而是实实在在走进了我们的生活。今天,我们要介绍的,不仅仅是一项技术革新,更是一场关于陪伴的革命——全球首款开源AI女友,DUIX,已经横空出世! 🚀 革命性的开源平台 DUIX,由硅基智能精心打造,不…

高中数学:数列-等差数列、等比数列的和与通项公式的关系

一、等差数列 1、通项公式与求和公式 2、性质 性质1 求和公式比上n&#xff0c;依然是一个等差数列。 性质2 等差数列中&#xff0c;每相邻m项和&#xff0c;构成的数列&#xff0c;依然是等差数列&#xff0c;公差&#xff1a;m2d 二、等比数列 1、通项公式与求和公式 a…

INVS利用gatearray实现post-mask的function ECO

随着现代IC的设计发展&#xff0c;设计的规模和复杂度逐步增加&#xff0c;对于验证完备性的挑战越来越大&#xff0c;加之TO的时间压力&#xff0c;芯片设计通常会出现下列的场景&#xff1a; 芯片回片一次点亮大部分的case都可以顺利通过小部分的功能需要修正 对于重要的特…

基于CentOS Stream 9平台 安装/卸载 Redis7.0.15

已更正systemctl管理Redis服务问题 1. 官方下载地址 https://redis.io/downloads/#redis-downloads 1.1 下载或上传到/opt/coisini目录下&#xff1a; mkdir /opt/coisini cd /opt/coisini wget https://download.redis.io/releases/redis-7.0.15.tar.gz2. 解压 tar -zxvf re…

.NET C# 装箱与拆箱

.NET C# 装箱与拆箱 目录 .NET C# 装箱与拆箱1 装箱 (Boxing)1.1 过程&#xff1a;1.2 示例&#xff1a; 2 拆箱 (Unboxing)2.1 过程&#xff1a;2.2 示例&#xff1a; 3 性能影响4 性能优化4.1 使用泛型集合示例&#xff1a; 4.2 使用Nullable<T>示例&#xff1a; 4.3 避…

速通数学建模 —— 查找数据

目录 百度搜索技巧 完全匹配搜索&#xff1a;查询词的外边加上双引号“ ” 标题必含关键词&#xff1a;查询词前加上intitle: 搜索文档&#xff1a;空格再输入filetype:文件格式 去掉不想要的&#xff1a;查询词后面加空格后加减号与关键字 知网查文献 先看知网的硕博士…