【用户登录】模块之登录认证+鉴权业务逻辑
用户登录——⭐认证功能的流程图:

⭐鉴权流程图:

用户登录功能的Java代码实现
1. 实体类-User
orm框架:JPA
@Table(name = "user_tab")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name="user_id")private Long id;@Column(name="user_name")private String username;@Column(name="user_password")private String password;@Column(name="user_phone")private String phone;@Column(name="user_nickname")private String nickname;@Column(name="user_create_by")private String createBy;@Column(name="user_create_time")private Date createTime;@Column(name="user_update_time")private Date updateTime;@Column(name="user_role_id")private Long roleId;
}
2. UserDao
@Repository
public interface UserDao extends JpaRepository<User,Long> {//根据user的username和password查询该用户User findByUsernameAndPassword(String username,String password);
}
3. UserService业务层接口
public interface UserService {//全查询List<User> findAllUsers();//1027-【从数据库读取用户名信息存入布隆过滤器中】void warnUpUsernames();//1027-【用户登录】User login(String username, String password);}
4. ⭐UserServiceImpl业务实现类
@Service
@Slf4j
public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;@Autowiredprivate StringRedisTemplate stringRedisTemplate;//全查询@Overridepublic List<User> findAllUsers() {return userDao.findAll();}//1027-【从数据库读取用户名信息存入布隆过滤器中】@Overridepublic void warnUpUsernames() {userDao.findAll().forEach(u -> {stringRedisTemplate.opsForValue().getOperations().execute(new DefaultRedisScript<Long>("return redis.call('bf.add',KEYS[1],ARGV[1])", Long.class),new ArrayList<String>() {{add("whiteUsernames");}}, u.getUsername());});}//1027-【用户登录】@Overridepublic User login(String username, String password) {if(!StringUtils.hasText(username)){throw new UsernameIsEmptyException("用户名为空异常");}username = username.trim();if(checkFromWhite(username)){throw new UsernameNotFoundException("用户名不存在异常");}User user = userDao.findByUsernameAndPassword(username, password);if(Objects.isNull(user)){throw new BadCredentialsException("用户名|密码错误");}return user;}//判断用户名是否存在于布隆过滤器private boolean checkFromWhite(String username) {Long isExist = stringRedisTemplate.opsForValue().getOperations().execute(new DefaultRedisScript<Long>("return redis.call('bf.exists',KEYS[1],ARGV[1])", Long.class),new ArrayList<String>() {{add("whiteUsernames");}}, username);return isExist.intValue() == 0;}
5. ⭐UserController控制层接口
@Api(tags = "用户模块接口")
@RestController
@RequestMapping("/api/user")
@Slf4j
public class UserController {@Autowiredprivate UserService userService;@Autowiredprivate StringRedisTemplate stringRedisTemplate;//1027-【全查询】@ApiOperation(value = "findAllUsers",notes = "查询所有用户,需要当前用户登录状态")@GetMapping("/findAllUsers")@BmsRole(value="1")public HttpResp<List<User>> findAllUsers(){return HttpResp.success(userService.findAllUsers());}//1027-【用户登录】@ApiOperation(value = "login",notes = "用户登录")@GetMapping("login")public HttpResp login(HttpServletResponse response, String username, String password){//首先调用AuthorityService的login方法进行用户登录验证,返回一个User对象。User user = userService.login(username,password);//然后生成一个JWT作为用户的身份认证凭证,其中包含了用户名和过期时间等信息。//使用JWT.create()创建JWT对象,并使用withClaim()方法设置用户名,withExpiresAt()方法设置过期时间。String salt = Base64.getEncoder().encodeToString((username+":"+password).getBytes(StandardCharsets.UTF_8));log.debug("user:{}",user);String token = JWT.create().withClaim("username", username).withClaim("roleId",""+user.getRoleId()).withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 30)) //30分钟令牌过期.sign(Algorithm.HMAC256(salt)); //使用Algorithm.HMAC256(salt)指定加密算法和密钥,对JWT进行签名。log.debug("用户验证通过,生成token为:{}",token);//将生成的JWT存储到Redis缓存中,使用stringRedisTemplate.opsForValue().set()方法设置键值对,并使用stringRedisTemplate.expire()方法设置过期时间stringRedisTemplate.opsForValue().set(token,salt);stringRedisTemplate.expire(token,60, TimeUnit.MINUTES); //60分钟redis缓存token过期response.addCookie(new Cookie("token",token)); //将JWT作为Cookie添加到HTTP响应中,使用response.addCookie()方法return HttpResp.success(user); //最后返回一个成功的响应,消息体中包含了登录成功的用户对象}}
用户认证解决方案
1. 配置部署拦截器
@Configuration
@Slf4j
public class BmsMvcConfig implements WebMvcConfigurer {@Beanpublic AuthorityInterceptor authorityInterceptor(){log.debug("BmsMvc拦截器启动成功:{}..........",new Date());return new AuthorityInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(authorityInterceptor()).addPathPatterns("/api/**").excludePathPatterns("/api/user/login");}
}
2. ⭐自定义拦截器
@Slf4j
public class AuthorityInterceptor implements HandlerInterceptor {@Autowiredprivate StringRedisTemplate stringRedisTemplate;/**** @param request* @param response* @param handler 当前拦截器拦截的方法* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.debug("已进入拦截器:{}",new Date());String token = request.getHeader("token");//1.从redis中读取token,如果不存在,则用户是非法用户,抛出自定义异常类InvalidTokenExceptionBoolean isRedis = stringRedisTemplate.hasKey(token);if(!isRedis) throw new InvalidTokenException("无效的token");String salt = stringRedisTemplate.opsForValue().get(token);log.debug("salt:{}",salt);DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(salt)).build().verify(token);//2.token验证完成正确String roleId = decodedJWT.getClaim("roleId").asString();log.debug("------->roleId:{}",roleId);HandlerMethod method = (HandlerMethod) handler;//System.out.println("----->"+method.getMethod().getDeclaredAnnotation(GetMapping.class));BmsRole bmsRole= method.getMethod().getDeclaredAnnotation(BmsRole.class);String requiredRolId = bmsRole.value();if(!roleId.equals(requiredRolId)){throw new PermissionDeniedException("您没有足够的权限");}//获取请求对象的角色名称//获取请求的地址(uri)
// String requestURI = request.getRequestURI();
// requestURI = requestURI.substring(requestURI.lastIndexOf("/") + 1);
// log.debug("请求路径uri:{}",requestURI);//URL/URI
// System.out.println(handler.getClass());return HandlerInterceptor.super.preHandle(request, response, handler);}
}
3. 在spring.factories文件加载部署
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.****.bms.authority.config.BmsMvcConfig,com.****.bms.authority.handler.UserExceptionHandler
未完待续......
相关文章:
【用户登录】模块之登录认证+鉴权业务逻辑
用户登录——⭐认证功能的流程图: ⭐鉴权流程图: 用户登录功能的Java代码实现 1. 实体类-User orm框架:JPA Table(name "user_tab") Entity Data NoArgsConstructor AllArgsConstructor public class User implements Serializ…...
开启CETOS 裸奔了一年的服务器开启firewall防火墙
记录一下关于firewall,博主非运维专家或服务器专家。 背景 客户有一台裸奔运行了一年多的系统有公网但发现没有开防火墙,iptables和firewall均是关闭状态,通过扫描发现很多漏洞。根据客户要求对端口进行重新梳理且关闭不必要或有潜在风险的…...
eslint识别不了别名解决方法
第一步 npm i eslint-import-resolver-alias -D第二步:在 eslintrc.js 配置 module.exports {settings: {import/resolver: {alias: {map: [// 这里参照webpack的别名配置映射[, ./src]],// 引用的时候可以忽略后缀extensions: [.vue, .js, .ts, .tsx, .jsx, .json…...
【windows 脚本】netsh命令
netsh 是 Windows 操作系统中的一个命令行工具,用于配置和管理网络设置。它提供了一系列的命令和参数,可以用于配置网络接口、防火墙、路由表等网络相关的设置。以下是一些常用的 netsh 命令和用法: 配置静态IP,IP地址、子网掩码和…...
二叉树三种遍历的递归与非递归写法
目录 编辑 一,前序遍历 题目接口: 递归解法: 非递归解法: 二,中序遍历 题目接口: 递归解法: 非递归写法: 三,后序遍历 题目接口: 递归解法&…...
虹科 | 解决方案 | 汽车示波器 远程诊断方案
车厂总部专家实时指导你修车 当一线汽修技师遇到疑难问题无从下手时,可以准备好pico汽车示波器套装,并戴上我们的M400智能AR眼镜,通过语音操作,呼叫主机厂的技术支持老师;老师通过AR眼镜上的摄像头老师可以实时看到现…...
Unity ScrollView最底展示
Unity ScrollView最底展示 问题方案逻辑 问题 比如在做聊天界面的时候我们肯定会使用到ScrollView来进行展示我们的聊天内容,那么这个时候来新消息的时候就需要最底展示,我认为这里有两种方案; 一种是通过算法每一条预制体的高度*一共多少…...
linux常用基本命令大全的使用(三)
🎬作者简介:大家好,我是青衿🥇 ☁️博客首页:CSDN主页石马农青衿 🌄每日一句:努力一点,优秀一点 📑前言 本文主要是linux常用基本命令面试篇文章,如果有什么…...
Qt 实现软件启动界面动画
实现软件启动界面,用到QSplashScreen类。 效果 启动界面 描述 QSplashScreen小部件提供了一个可以在应用程序启动期间显示的启动画面。 启动画面通常是在应用程序启动时显示的小部件。启动画面通常用于启动时间较长的应用程序(例如需要花费一些时间来建…...
2000-2021年三批“智慧城市”试点名单匹配数据
2000-2021年三批“智慧城市”试点名单匹配数据 1、时间:2000-2021年 2、指标:行政区划代码、地区、所属省份、年份、智慧城市试点、最早试点年份 3、来源:住建部公布的三批“国家智慧城市名单” 4、说明:内含原始文件和匹配结…...
H5游戏分享-烟花效果
<!DOCTYPE html> <html dir"ltr" lang"zh-CN"> <head> <meta charset"UTF-8" /> <meta name"viewport" content"widthdevice-width" /> <title>点击夜空欣赏烟花</title> <sc…...
底层驱动day8作业
代码: //驱动程序 #include<linux/init.h> #include<linux/module.h> #include<linux/of.h> #include<linux/of_gpio.h> #include<linux/gpio.h> #include<linux/timer.h>struct device_node *dnode; //unsigned int gpiono; …...
openWRT SFTP 实现远程文件安全传输
🔥博客主页: 小羊失眠啦. 🔖系列专栏: C语言、Linux、 Cpolar ❤️感谢大家点赞👍收藏⭐评论✍️ 文章目录 前言 1. openssh-sftp-server 安装2. 安装cpolar工具3.配置SFTP远程访问4.固定远程连接地址 前言 本次教程我…...
麒麟KYLINOS2303版本上使用KDE桌面共享软件
原文链接:麒麟KYLINOS2303版本上使用KDE桌面共享软件 hello,大家好啊,今天给大家推荐一个在麒麟KYLINOS桌面操作系统2303版本上使用KDE桌面共享软件的文章,通过安装KDE桌面共享软件,可以让远程vnc客户端连接访问本机桌…...
H5游戏源码分享-手机捉鬼游戏
H5游戏源码分享-手机捉鬼游戏 一款考验手速的游戏 <!DOCTYPE html> <html><head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"><title>手机捉鬼 微信HTML5在线朋友圈游戏</title><meta name&…...
vite中将css,js文件归类至文件夹
build: {chunkSizeWarningLimit: 1500,rollupOptions: {output: {// 最小化拆分包manualChunks(id) {if (id.includes(node_modules)) {return id.toString().split(node_modules/)[1].split(/)[0].toString()}},// 用于从入口点创建的块的打包输出格式[name]表示文件名,[hash]…...
【通信原理】第一章|绪论|信息度量和通信系统的性能指标
前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助。 高质量博客汇总 绪论 1. 信息和信息的度量 定义信息…...
基于STM32+OneNet设计的物联网智能鱼缸(2023升级版)
基于STM32+OneNet设计的智能鱼缸(升级版) 一、前言 随着物联网技术的快速发展,智能家居和智能养殖领域的应用越来越广泛。智能鱼缸作为智能家居和智能养殖的结合体,受到了越来越多消费者的关注。本项目设计一款基于STM32的物联网智能鱼缸,通过集成多种传感器和智能化控制模…...
NET-MongoDB的安装使用
一.下载 MongoDB 点击 Select package 选择自己所需版本后点击下载,本文选用Windows 6.0版本以上 二、配置MongoDB 在 Windows 上,MongoDB 将默认安装在 C:\Program Files\MongoDB 中。 将 C:\Program Files\MongoDB\Server\version_numbe…...
简化geojson策略
1、删除无用的属性,也就是字段,在shp的时候就给删了 用arcgis等等软件都可以做到 2、简化坐标的小数位数 (1)网上推荐的办法,俺不会Python… github.com/perrygeo/geojson-precision (2)曲线…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
使用ch340继电器完成随机断电测试
前言 如图所示是市面上常见的OTA压测继电器,通过ch340串口模块完成对继电器的分路控制,这里我编写了一个脚本方便对4路继电器的控制,可以设置开启时间,关闭时间,复位等功能 软件界面 在设备管理器查看串口号后&…...
VSCode 没有添加Windows右键菜单
关键字:VSCode;Windows右键菜单;注册表。 文章目录 前言一、工程环境二、配置流程1.右键文件打开2.右键文件夹打开3.右键空白处打开文件夹 三、测试总结 前言 安装 VSCode 时没有注意,实际使用的时候发现 VSCode 在 Windows 菜单栏…...
