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

⭐鉴权流程图:

用户登录功能的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)曲线…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
