SpringBoot Vue使用Jwt实现简单的权限管理
为实现Jwt简单的权限管理,我们需要用Jwt工具来生成token,也需要用Jwt来解码token,同时需要添加Jwt拦截器来决定放行还是拦截。下面来实现:
1、gradle引入Jwt、hutool插件
implementation 'com.auth0:java-jwt:3.10.3'implementation 'cn.hutool:hutool-all:5.3.7'
2、Jwt工具类,提供静态方法生成token,和根据请求携带的token查找user信息
package com.zzz.simple_blog_backend.utils;import ......@Component
public class JwtTokenUtils {@Autowiredprivate UserService userService;private static UserService userServiceStatic;@PostConstruct//在spring容器初始化后执行该方法public void setUserService() {userServiceStatic = userService;}//生成Tokenpublic static String genToken(String userId,String passwordSign) {return JWT.create().withAudience(userId)//放入载荷.withExpiresAt(DateUtil.offsetHour(new Date(), 2))//2小时后过期.sign(Algorithm.HMAC256(passwordSign));//密码签名作为密钥}//通过token获取当前登录用户信息public static User getCurrentUser() {String token = null;HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();//1、获取tokentoken = request.getHeader("token");if (StrUtil.isBlank(token)) {token = request.getParameter("token");}if (StrUtil.isBlank(token)) {throw new RuntimeException("没有token,请重新登录");}String userId;User user;try {userId = JWT.decode(token).getAudience().get(0);} catch (Exception e) {throw new RuntimeException("token验证失败,请重新登录!!!");}user = userServiceStatic.findById(Integer.parseInt(userId));if(user==null) {throw new RuntimeException("用户id不存在,请重新登录!!!");}//3、用密码签名,解码判断tokentry {JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();jwtVerifier.verify(token);} catch (JWTVerificationException e) {throw new CustomException(001, "token验证失败,请重新登录!!!");}return user;}
}
3、Jwt拦截器
SpringBoot添加拦截器,excludePathPatterns
可以指定不拦截的页面,RestController
指定了请求前缀,控制器类要用@RestController
代替@Controller
,addInterceptor
添加了jwtInterceptor
拦截器。
package com.zzz.simple_blog_backend.config;import ...@Configuration
public class WebConfig implements WebMvcConfigurer{@Autowiredprivate JwtInterceptor jwtInterceptor;@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {//指定restcontroller统一接口前缀configurer.addPathPrefix("/api", clazz -> clazz.isAnnotationPresent(RestController.class));}@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 加自定义拦截器 给特定请求放行registry.addInterceptor(jwtInterceptor).addPathPatterns("/api/**").excludePathPatterns("/api/user/login","/api/user/register");}
}
仔细的童靴会发现JwtTokenUtils.getCurrentUser()
方法和JwtInterceptor
的拦截方法很像,主要区别就在if(user.getRole()!=0)
的判断。所以JwtInterceptor
只会给管理员放行,如果需要给普通用户放行而未登录用户不放行,那请求路径先添加到excludePathPatterns
,并且控制类对应的响应方法第一句就先调用JwtTokenUtils.getCurrentUser()
判断是否用户已登录。
package com.zzz.simple_blog_backend.config;import ......@Component
public class JwtInterceptor implements HandlerInterceptor{@Autowiredprivate UserService userService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {//1、获取tokenString token = request.getHeader("token");if (StrUtil.isBlank(token)) {token = request.getParameter("token");}if (StrUtil.isBlank(token)) {throw new RuntimeException("没有token,请重新登录");}//2、开始认证 解码token,获得userIdString userId;User user;try {userId = JWT.decode(token).getAudience().get(0);} catch (Exception e) {throw new RuntimeException("token验证失败,请重新登录!!!");}user = userService.findById(Integer.parseInt(userId));if(user==null) {throw new RuntimeException("用户id不存在,请重新登录!!!");}if(user.getRole()!=0) {throw new RuntimeException("非管理员账号,无权访问!!!");}//3、用密码签名,解码判断tokentry {JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();jwtVerifier.verify(token);} catch (JWTVerificationException e) {throw new RuntimeException("token验证失败,请重新登录!!!");}//token验证成功,放行return true;
// return HandlerInterceptor.super.preHandle(request, response, handler);}
}
4、前后端登录操作
登录后 后端返回带token不带密码的user数据
@PostMapping("user/login")@ResponseBodypublic CommonResult<Object> login(@RequestBody User user){user = userService.findByUsernameAndPassword(user);if (user == null) {return CommonResult.failed(001, Message.createMessage("用户名或密码错误!!!"));} else {//生成用户对应的TokenString token = JwtTokenUtils.genToken(user.getId().toString(), user.getPassword());user.setToken(token);//不传输密码user.setPassword("");return CommonResult.success(user);}}
前端保存带token的user
//axios的post请求成功后操作localStorage.setItem("user",JSON.stringify(response.data.data));//保存用户信息
5、前端每次请求都携带token信息
假设已安装axios,Axios.interceptors.request
拦截用户所有请求,添加token信息后再发送请求,这样后端就可以判断了。
import Axios from 'axios'Vue.prototype.$http = Axios;
//添加向后端发起请求的服务器地址前缀
Axios.defaults.baseURL=AIOS_BASE_URL; // "http://127.0.0.1/api"
//设置请求超时时间
Axios.defaults.timeout=5000;//axios拦截器
//对接口request拦截
Axios.interceptors.request.use(function(config){//发起增删改查请求时,带上token认证var user = localStorage.getItem("user");if(user){config.headers["token"] = JSON.parse(user).token;}return config;
})
//携带证书 session id 跨域请求的话需要
Axios.defaults.withCredentials = true
总结
Jwt实现权限管理的原理是登录成功后 后端端生成token密钥,随着用户信息发送给客户端,客户端接受并保存信息到本地localStorage。以后每次需要权限验证时,根据客户端返回的携带token信息,后端进行拦截并解码校验,通过则放行,否则抛异常。如果要抛异常时,返回错误信息给前端,请看链接。
相关文章:
SpringBoot Vue使用Jwt实现简单的权限管理
为实现Jwt简单的权限管理,我们需要用Jwt工具来生成token,也需要用Jwt来解码token,同时需要添加Jwt拦截器来决定放行还是拦截。下面来实现: 1、gradle引入Jwt、hutool插件 implementation com.auth0:java-jwt:3.10.3implementatio…...

java中的多态
多态基础了解: 面向对象的三大特征:封装,继承,多态。 有了面向对象才有继承和多态,对象代表什么,就封装对应的数据,并提供数据对应的行为,可以把零散的数据和行为进行封装成一个整…...

【数据结构】:用Java实现链表
在 ArrayList 任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为 O(n),效率比较低,因此 ArrayList 不适合做任意位置插入和删除比较多的场景。因此:java 集合中又引入了 LinkedList&…...

前端开发知识(三)-javascript
javascript是一门跨平台、面向对象的脚本语言。 一、引入方式 1.内部脚本:使用<script> ,可以放在任意位置,也可以有多个,一般是放在<body></body>的下方。 2.外部脚本:单独编写.js文件ÿ…...
Windows图形界面(GUI)-MFC-C/C++ - MFC绘图
公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 MFC绘图 绘图基础 CPaintDC 实例代码 MFC绘图 绘图基础 设备上下文(Device Context, DC): 设备上下文是一个Windows GDI(图形设备接口)…...

51单片机-第五节-串口通信
1.什么是串口? 串口是通讯接口,实现两个设备的互相通信。 单片机自带UART,其中引脚有TXD发送端,RXD接收端。且电平标准为TTL(5V为1,0V为0)。 2.常见电平标准: (1)TTL电…...
【Linux常用命令】之df命令
Linux常用命令之df命令 文章目录 Linux常用命令之df命令常用命令之df背景介绍 总结 作者简介 听雨:一名在一线从事多年研发的程序员,从事网站后台开发,熟悉java技术栈,对前端技术也有研究,同时也是一名骑行爱好者。 D…...

2024年起重信号司索工(建筑特殊工种)证模拟考试题库及起重信号司索工(建筑特殊工种)理论考试试题
题库来源:安全生产模拟考试一点通公众号小程序 2024年起重信号司索工(建筑特殊工种)证模拟考试题库及起重信号司索工(建筑特殊工种)理论考试试题是由安全生产模拟考试一点通提供,起重信号司索工(建筑特殊工种)证模拟考试题库是根据起重信号司索工(建筑特…...
AWS全服务历史年表:发布日期、GA和服务概述一览 (全)
我一直在尝试从各种角度撰写关于Amazon Web Services(AWS)的信息和魅力。由于我喜欢技术历史,这次我总结了AWS服务发布的历史年表。 虽然AWS官方也通过“Whats New”发布了官方公告,但我一直希望能有一篇文章将公告日期、GA日期&…...
Leetcode 2824. 统计和小于目标的下标对数目
2824. 统计和小于目标的下标对数目 2824. 统计和小于目标的下标对数目 一、题目描述二、我的想法 一、题目描述 给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 target ,请你返回满足 0 < i < j < n 且 nums[i] nums[j] < target 的下标对…...
TCP服务器主动断开客户端
自定义消息函数 afx_msg LRESULT CbaseMFCprojectDlg::OnOnsocketbartender(WPARAM wParam, LPARAM lParam) WPARAM wParam:消息来源 res recv(wParam, cs, 65535, 0);获取这个客户端端口socket通道里面的信息长度为65535存放在cs里面 如果获取得到res0即是说明该客户端已经断…...
接口自动化中json.dumps()跟json.loads()区别详解
接口自动化中对于参数处理经常会用到json.dumps()跟json.loads(),下面主要分享一下自己使用总结 1.主要区别 json.dumps() 用于将字典转换为字符串格式 json.loads()用于将字符串转换为字典格式 import jsondict1 {"name":"amy","gender":woma…...

计算机网络-配置双机三层互联(静态路由方式)
目录 交换机工作原理路由器工作原理路由信息表组成部分路由器发决策 ARP工作原理配置双机三层互联(静态路由方式) 交换机工作原理 MAC自学习过程 初始状态: 刚启动的交换机的MAC地址表是空的。 学习过程: 当交换机收到一个数据帧…...
ES(Elasticsearch)常用的函数有哪些?
【电子书大全】内含上千本顶级编程书籍,是程序员必备的电子书资源包,并且会不断地更新,助你在编程的道路上更上一层楼! 链接: https://pan.baidu.com/s/1yhPJ9LmS_z5TdgIgxs9NvQ?pwdyyds > 提取码: yyds Elasticsearch&#x…...

【计算机网络】ICMP报文实验
一:实验目的 1:掌握ICMP报文的各种类型及其代码。 2:掌握ICMP报文的格式。 3:深入理解TTL的含义(Time to Live,生存时间)。 二:实验仪器设备及软件 硬件:RCMS-C服务器…...

transformers进行学习率调整lr_scheduler(warmup)
一、get_scheduler实现warmup 1、warmup基本思想 Warmup(预热)是深度学习训练中的一种技巧,旨在逐步增加学习率以稳定训练过程,特别是在训练的早期阶段。它主要用于防止在训练初期因学习率过大导致的模型参数剧烈波动或不稳定。…...

智能优化算法之灰狼优化算法(GWO)
智能优化算法是一类基于自然界中生物、物理或社会现象的优化技术。这些算法通过模拟自然界中的一些智能行为,如遗传学、蚁群觅食、粒子群体运动等,来解决复杂的优化问题。智能优化算法广泛应用于各种工程和科学领域,因其具有全局搜索能力、鲁…...

昇思25天学习打卡营第17天|计算机视觉
昇思25天学习打卡营第17天 文章目录 昇思25天学习打卡营第17天ShuffleNet图像分类ShuffleNet网络介绍模型架构Pointwise Group ConvolutionChannel ShuffleShuffleNet模块构建ShuffleNet网络 模型训练和评估训练集准备与加载模型训练模型评估模型预测 打卡记录 ShuffleNet图像分…...
Windows图形界面(GUI)-MFC-C/C++ - 键鼠操作
公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 MFC鼠标 派发流程 鼠标消息(客户区) 鼠标消息(非客户) 坐标处理 客户区 非客户 坐标转换 示例代码 MFC键盘 击键消息 虚拟键代码 键状态 MFC鼠标 派发流程 消息捕获&#…...
Angular 18.2.0 的新功能增强和创新
一.Angular 增强功能 Angular 是一个以支持开发强大的 Web 应用程序而闻名的平台,最近发布了 18.2.0 版本。此更新带来了许多新功能和改进,进一步增强了其功能和开发人员体验。在本文中,我们将深入探讨 Angular 18.2.0 为开发人员社区提供的…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...

GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...

Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...
[特殊字符] 手撸 Redis 互斥锁那些坑
📖 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作,想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁,也顺便跟 Redisson 的 RLock 机制对比了下,记录一波,别踩我踩过…...