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

⭐鉴权流程图:

用户登录功能的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)曲线…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...
