SpringBoot集成JWT token实现权限验证
JWT=JSON Web Token
1. JWT的组成
JWT==Header,Payload,Signature==>abc.def.xyz


地址:JSON Web Tokens - jwt.er
1.1 Header
Header:标头。
两个组成部分:令牌的类型(JWT)和所使用的签名算法,经过Base64 Url编码后形成的JWT的第一部分。
{"type":"JWT","alg":"HS256"
}
1.2 Payload
Payload---有效负载。存放用户自定义消息
注意点:是以明文的形式进行展示,以Base64进行编码。
{“sub":"123","name":"jon","admin":true
}
1.3 Signature
signature--签名。使用标头的算法和私钥对第一部分和第二部分进行加密,通过Base64 Url编码后形成JWT的第三部分。
var encodeString =base64UrlEncode(header)+"."+base64UrlEncode(payload);
var signature=HMACSHA356(encodeString,secret);
2.JWT的基本使用
1.导入pom JWT依赖
JDK1.8以下的加入JWT依赖即可
<!--JWT--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
JDK1.8以上的加上其他
<!--JWT--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.0</version></dependency><dependency><groupId>com.sun.xml.bind</groupId><artifactId>jaxb-impl</artifactId><version>2.3.0</version></dependency><dependency><groupId>com.sun.xml.bind</groupId><artifactId>jaxb-core</artifactId><version>2.3.0</version></dependency>
2.创建JWT
//毫秒private long time=1000*60*60*24;//签名private String signature="admin";/*JWT加密*/@Testpublic void jwt(){//构建JWT对象:Jwts.builder()JwtBuilder jwtBuilder = Jwts.builder();String jwtToken = jwtBuilder//header:头部.setHeaderParam("typ", "JWT").setHeaderParam("alg", "HS256")//payload:载荷.claim("username", "tom").claim("role", "admin").setSubject("admin-test")//有效时间===>一天=当前时间+24小时//获得当前的系统时间:System.currentTimeMillis().setExpiration(new Date(System.currentTimeMillis() + time))//设置id字段.setId(UUID.randomUUID().toString())//signature:签名//注意点:这个签名算法要与前面的算法一致//设置加密算法和签名.signWith(SignatureAlgorithm.HS256, signature)//将前面3个重要信息拼接起来,使用”."来连接.compact();System.out.println(jwtToken);}
3.验证JWT
@Test/*验证JWT*/public void checkJwt(){String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InRvbSIsInJvbGUiOiJhZG1pbiIsInN1YiI6ImFkbWluLXRlc3QiLCJleHAiOjE2OTM2MzgzMDMsImp0aSI6ImU5ZjY3ZjBhLWE0NTAtNGYzYy1hYTY3LTU3ZGMwOWRjMDM4ZCJ9.FxA5c91E2bk2KW1rdMo8jlmClXgn7r2mVSaXs19Qzzk";//Jwts.parser():解析JwtParser jwtParser = Jwts.parser();//验证该token是否符合JWT规则boolean result = Jwts.parser().isSigned(token);System.out.println(result);//true}
4.解析JWT
@Test/*解析JWT*/public void parseJwt(){String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InRvbSIsInJvbGUiOiJhZG1pbiIsInN1YiI6ImFkbWluLXRlc3QiLCJleHAiOjE2OTM2MzgzMDMsImp0aSI6ImU5ZjY3ZjBhLWE0NTAtNGYzYy1hYTY3LTU3ZGMwOWRjMDM4ZCJ9.FxA5c91E2bk2KW1rdMo8jlmClXgn7r2mVSaXs19Qzzk";//获取JWT的解析对象JwtParser jwtParser = Jwts.parser();//通过signature对token进行签名,解开//parseClaimsJws:将JWT转换为key-value的形式,通过key来获取对应的value//Jws<Claims>:类似于Map集合Jws<Claims> claimsJws = jwtParser.setSigningKey(signature).parseClaimsJws(token);//获取Jws对象中的数据:get(key)表示根据key来获取value//相当于将header和payload封装为一个claimsClaims claims = claimsJws.getBody();//存储的是用户保存的数据Object username = claims.get("username");System.out.println(username);Object role = claims.get("role");System.out.println(role);String id = claims.getId();System.out.println(id);//签名String subject = claims.getSubject();System.out.println(subject);//有效期Date time = claims.getExpiration();System.out.println(time);}
3.SpringBoot + vue +JWT
1.导入pom JWT依赖
JDK1.8以下的加入JWT依赖即可
<!--JWT--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
JDK1.8以上的还要加上以下依赖
<!--JWT--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.0</version></dependency><dependency><groupId>com.sun.xml.bind</groupId><artifactId>jaxb-impl</artifactId><version>2.3.0</version></dependency><dependency><groupId>com.sun.xml.bind</groupId><artifactId>jaxb-core</artifactId><version>2.3.0</version></dependency><dependency><groupId>javax.activation</groupId><artifactId>activation</artifactId><version>1.1.1</version></dependency>
2.导入工具类
public class JwtUtil {//毫秒private static long time=1000*60*60*24;//签名private static String signature="admin";public static String createToken(){//构建JWT对象:Jwts.builder()JwtBuilder jwtBuilder = Jwts.builder();String jwtToken=jwtBuilder//header.setHeaderParam("typ", "JWT").setHeaderParam("alg", "HS256")//payload.claim("username", "admin").claim("role", "admin").setSubject("admin-test")//有效时间===>一天=当前时间+24小时//获得当前的系统时间:System.currentTimeMillis().setExpiration(new Date(System.currentTimeMillis()+time)).setId(UUID.randomUUID().toString())//signature//注意点:这个签名算法要与前面的算法一致.signWith(SignatureAlgorithm.HS256,signature)//将前面3个重要信息拼接起来.compact();return jwtToken;}
}
3.在后台解决跨域问题
@Configuration//配置类
public class CoreConfiguration implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**")//所有接口.allowCredentials(true)//是否发送Cookie.allowedOriginPatterns("*")//支持域.allowedMethods("GET","POST","PUT","DELETE")//支持方法.allowedHeaders("*").exposedHeaders("*");}
}
4.前台登录界面

5.前端代码
methods:{handleSubmit(){this.$refs.ruleForm.validate((valid)=>{if(valid){let _this=thisaxios.get("http://localhost:8080/login",{param:_this.ruleForm}).then(function (response){console.log(response.data)})}})}}

6.进行路由跳转,并且将用户信息存到本地存储中
JSON.stringify-->将JSON转换为字符串
handleSubmit(){this.$refs.ruleForm.validate((valid)=>{if(valid){let _this=thisaxios.get("http://localhost:8080/login",{param:_this.ruleForm})./*带着用户输入的用户名和密码*/then(function (response){console.log(response.data)//如果data不为空,则表示登录成功if(response.data!=null){//使用localStorage//将JSON转换为字符串localStorage.setItem('access-admin',JSON.stringify(response.data))//跳转到首页_this.$router.replace({path:"/"})}})}})}
7.将用户信息展示到页面中
JSON.parse--->将字符串转换为JSON
<template>
<div>欢迎回来:{{admin.username}}
</div>
</template>data(){return{admin:''}},created() {
//获取数据this.admin=JSON.parse(window.localStorage.getItem("access-admin"));},
8.添加验证用户信息是否存在【在路由中写】
/router/index.js
router.beforeEach((to,from,next)=>{if(to.path.startsWith('/login')){window.localStorage.removeItem('access-admin')next()}else {let admin=JSON.parse(window.localStorage.getItem('access-admin'))if(!admin){next({path:'/login'})}else {//校验token合法性axios({url:'http://localhost:8080/checkeToken',method:'get',headers:{token:admin.token}}).then((response)=>{if(!response.data){console.log("校验失败");next({path:'/error'})}})}}
})

9.后端验证Token方法
UserController
/*** 验证token方法*/@GetMapping("/checkToken")public Boolean checkToken(HttpServletRequest request){//因为前端是将数据存储在header,所以我们要是有getHeaderString token = request.getHeader("token");return JwtUtil.checkToken(token);}
JwtUtil
/*** 校验token是否正确*/public static boolean checkToken(String token){if (token==null){return false;}try {//解析Jws<Claims> claimsJws = Jwts.parser().setSigningKey(signature).parseClaimsJws(token);}catch (Exception e){e.printStackTrace();}return true;}
4.Springboot+JWT
User
@Data
public class User {private String username;private String password;private String token;
}
UserController:生成JWT令牌
public class UserController {private final String USERNAME = "admin";private final String PASSWORD = "123123";@GetMapping("/login")public User login(User user){//判断是否正确if(USERNAME.equals(user.getUsername()) && PASSWORD.equals(user.getPassword())){//添加token;token保存到user对象//定义一个工具类,将生成JWTuser.setToken(JwtUtil.createToken());return user;}return null;}
}
JwtUtil:生成JWT令牌
public class JwtUtil {//毫秒private static long time=1000*60*60*24;//签名private static String signature="admin";public static String createToken(){//构建JWT对象:Jwts.builder()JwtBuilder jwtBuilder = Jwts.builder();String jwtToken=jwtBuilder//header.setHeaderParam("typ", "JWT").setHeaderParam("alg", "HS256")//payload.claim("username", "admin").claim("role", "admin").setSubject("admin-test")//有效时间===>一天=当前时间+24小时//获得当前的系统时间:System.currentTimeMillis().setExpiration(new Date(System.currentTimeMillis()+time)).setId(UUID.randomUUID().toString())//signature//注意点:这个签名算法要与前面的算法一致.signWith(SignatureAlgorithm.HS256,signature)//将前面3个重要信息拼接起来.compact();return jwtToken;}
}
【前端直接传递token】
JwtUtil:验证JWT是否过期
/*** 校验token是否过期*/public static boolean checkToken(String token){if (token==null || token==""){return false;//false表示令牌过期}try {//拿到JWT对象Jws<Claims> claimsJws = Jwts.parser().setSigningKey(signature).parseClaimsJws(token);}catch (Exception e){e.printStackTrace();}return true;}
UserController:验证JWT是否过期
/*** 验证token是否过期:前端传递token*/@GetMapping("/checkToken")public Boolean checkToken(String token){return JwtUtil.checkToken(token);}
【将Token放入请求头中,使用request】
JwtUtil:验证JWT是否过期
/*** 校验token是否过期*/public static boolean checkToken(String token){if (token==null || token==""){return false;//false表示令牌过期}try {//拿到JWT对象Jws<Claims> claimsJws = Jwts.parser().setSigningKey(signature).parseClaimsJws(token);}catch (Exception e){e.printStackTrace();}return true;}
UserController:验证JWT是否过期
/*** 验证token是否过期:前端将数据封装在请求头中* @param request* @return*/public boolean checkToken(HttpServletRequest request){//getHeader中的key要与前端通过一致String token = request.getHeader("token");//key-->tokenreturn JwtUtil.checkToken(token);}
解决跨域问题
参考:SpringBoot跨域请求的问题_m0_63077733的博客-CSDN博客
@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**") // 所有接口.allowCredentials(true) // 是否发送 Cookie.allowedOriginPatterns("*") // 支持域.allowedMethods("GET", "POST", "PUT", "DELETE") // 支持方法.allowedHeaders("*").exposedHeaders("*");}
}
拦截器实现Token验证
@Configuration
public class TokenInterceptor implements HandlerInterceptor {//在请求处理方法被调用之前被调用@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//前提:token放在请求头中String token = request.getHeader("token");if (!JwtUtil.checkToken(token)) {return false;//验证失败}return true;}
}
相关文章:
SpringBoot集成JWT token实现权限验证
JWTJSON Web Token 1. JWT的组成 JWTHeader,Payload,Signature>abc.def.xyz 地址:JSON Web Tokens - jwt.er 1.1 Header Header:标头。 两个组成部分:令牌的类型(JWT)和所使用的签名算法,经过Base64 Url编码后形成…...
算法通关村第11关【青铜】| 位运算基础
1.数字在计算机中的表示 原码、反码和补码都是计算机中用于表示有符号整数的方式。它们的使用旨在解决计算机硬件中的溢出和算术运算问题。 原码(Sign-Magnitude): 原码最简单,它的表示方式是用最高位表示符号位,0表示…...
无涯教程-Android - RadioGroup函数
RadioGroup类用于单选按钮集。 如果我们选中属于某个单选按钮组的一个单选按钮,它将自动取消选中同一组中以前选中的任何单选按钮。 RadioGroup属性 以下是与RadioGroup控制相关的重要属性。您可以查看Android官方文档以获取属性的完整列表以及可以在运行时更改这些属性的相关…...
降噪音频转录 Krisp: v1.40.7 Crack
主打人工智能降噪服务的初创公司「Krisp」近期宣布推出音频转录功能,能对电话和视频会议进行实时设备转录。该软件还整合的ChatGPT,以便快速总结内容,开放测试版于今天上线。 随着线上会议越来越频繁,会议转录已成为团队工作的重…...
基于React实现:弹窗组件与Promise的有机结合
背景 弹窗在现代应用中是最为常见的一种展示信息的形式,二次确认弹窗是其中最为经典的一种。当我们在React,Vue这种数据驱动视图的前端框架中渲染弹窗基本是固定的使用形式。 使用方式:创建新的弹窗组件,在需要弹窗的地方引用并…...
docker使用(一)生成,启动,更新(容器暂停,删除,再生成)
docker使用(一) 编写一个 Dockerfile构建镜像构建失败构建成功 运行镜像运行成功 修改代码后再次构建请不要直接进行构建,要将原有的旧容器删除或暂停停止成功删除成功再次构建且构建成功! 要创建一个镜像,你可以按照以…...
用Qt自制一个小闹钟
小闹钟 功能 当按下启动按钮时,停止按钮可用,启动按钮不可用,闹钟无法设置,无法输入自定义内容 当按下停止按钮时,暂停播报,启动按钮可用,闹钟可以设置,可以输入自定义内容 .pro文…...
Vue2.0/Vue3.0使用xlsx+xlsx-style实现导出Excel文件
一、依赖导入 1、Vue2 Webpack构建的 npm i xlsx npm i xlsx-style npm i file-saver同时修改以下: 解决 Can’t resolve ‘./cptable’ in ‘…’ 的问题,在 vue.config.js 文件中加入该配置 module.exports {externals: {./cptable: var cptable}…...
【Kafka系列】(一)Kafka入门
有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 Kafka是什么? 一句话概括:「Apache Kafka 是一款开源的消息引擎系统」 什么是消息引擎系统&#…...
外包干了2个月,技术退步明显了...
先说一下自己的情况,大专生,19年通过校招进入湖南某软件公司,干了接近4年的功能测试,今年8月份,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...
python实现语音识别
1. 首先安装依赖库 pip install playsound # 该库用于播放音频文件 pip install speech_recognition # 该库用于语音识别 pip install PocketSphinx # 语音识别模块中只有sphinx支持离线的,使用该模块需单独安装 pip install pyttsx3 # 该库用于将文本转换为语音播…...
java八股文面试[多线程]——线程的状态
5种状态一般是针对传统的线程状态来说(操作系统层面) 6种状态:Java中给线程准备的 NEW:Thread对象被创建出来了,但是还没有执行start方法。 RUNNABLE:Thread对象调用了start方法,就为RUNNABLE状…...
Go学习[合集]
文章目录 Go学习-Day1Go学习-Day2标识符变量基础语法字符串类型类型转换string和其他基本类型转换其他类型转stringstring转其他类型 指针类型运算符标准IO分支语句 Go学习-Day3循环语句函数声明init函数匿名函数闭包defer Go学习-Day4函数值传递,引用传递常用的函数…...
代码随想录算法训练营第42天 | ● 01背包问题,你该了解这些! ● 01背包问题,你该了解这些! 滚动数组 ● 416. 分割等和子集
文章目录 前言一、01背包问题,你该了解这些!二、01背包问题,你该了解这些! 滚动数组三、416. 分割等和子集总结 前言 01背包 一、01背包问题,你该了解这些! 确定dp数组以及下标的含义 对于背包问题&#x…...
解决DNS服务器未响应错误的方法
当你将设备连接到家庭网络或具有互联网接入功能的Wi-Fi热点时,由于各种原因,互联网连接可能无法正常工作。本文中的说明适用于Windows 10、Windows 8和Windows 7。 无法连接到DNS服务器的原因 故障的一类与域名系统有关,域名系统是世界各地互联网提供商使用的分布式名称…...
SpringBoot的HandlerInterceptor拦截器使用方法
一、创建拦截器 通过实现HandlerInterceptor接口创建自己要使用的拦截器 import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.…...
java 常用 jar 包
1 Lombok 是一个 java 类库,它利用注解方式自动生成 java bean 中 getter、setter、equals 等方法,还能自动生成 logger、toString、hashCode、builder 等 日志相关变量、Object 类方法或设计模式相关的方法,能够让你的 代码更简洁࿰…...
C#面试十问
1:C#中变量类型分为哪两种?它们的区别是什么?2:Class和Struct的区别?3:C#中类的修饰符和类成员的修饰符有哪些?4:面向对象的三个特征(特点)是什么?…...
Day 41 动态规划part03 : 343. 整数拆分 96.不同的二叉搜索树
96. 不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n 3 输出:5示例 2: 输入:n 1…...
四轴飞行器的电池研究(MatlabSimulink仿真)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...
【阅读笔记】MemOS: 大语言模型内存增强生成操作系统
核心速览 研究背景 研究问题:这篇文章要解决的问题是当前大型语言模型(LLMs)在处理内存方面的局限性。LLMs虽然在语言感知和生成方面表现出色,但缺乏统一的、结构化的内存架构。现有的方法如检索增强生成(RA…...
RKNN开发环境搭建2-RKNN Model Zoo 环境搭建
目录 1.简介2.环境搭建2.1 启动 docker 环境2.2 安装依赖工具2.3 下载 RKNN Model Zoo2.4 RKNN模型转化2.5编译C++1.简介 RKNN Model Zoo基于 RKNPU SDK 工具链开发, 提供了目前主流算法的部署例程. 例程包含导出RKNN模型, 使用 Python API, CAPI 推理 RKNN 模型的流程. 本…...
RFID推动新能源汽车零部件生产系统管理应用案例
RFID推动新能源汽车零部件生产系统管理应用案例 一、项目背景 新能源汽车零部件场景 在新能源汽车零部件生产领域,电子冷却水泵等关键部件的装配溯源需求日益增长。传统 RFID 溯源方案采用 “网关 RFID 读写头” 模式,存在单点位单独头溯源、网关布线…...
