【第4章】SpringBoot实战篇之登录优化(含redis使用)

文章目录

  • 前言
  • 一、整合redis
    • 1. 引入库
    • 2. 配置
  • 二、登录优化
    • 1.登录
    • 2.拦截器
    • 3. 登出
    • 4. 修改密码
  • 总结


前言

上一章的登录接口,我们将用户登录信息放置于Map中,存在一个问题,集群部署无法共享以及应用停止用户登录信息即丢失,接下来我们整合redis来整合这个问题。


一、整合redis

1. 引入库

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2. 配置

spring:data:redis:host: 192.168.137.192port: 6379database: 0username: defaultpassword: 21797d7480c1270b848a1524128671b31dcad0725762cf41cc81c21e15fa35b2

二、登录优化

1.登录

@Autowired
StringRedisTemplate stringRedisTemplate;
@RequestMapping("login")
public Result login(@Valid User loginUser){String message="用户名/密码不正确";User user = userSerivce.findUserByName(loginUser.getUsername());if(user!=null){//用户存在if(user.getPassword().equals(Md5Util.getMD5String(loginUser.getPassword()))){//密码正确Map<String,Object> claims=new HashMap();claims.put("userId",user.getId());claims.put("username",user.getUsername());String token = JwtUtils.create(claims);stringRedisTemplate.opsForValue().set(user.getId().toString(),token,24, TimeUnit.HOURS);return Result.success("登录成功",token);}}return Result.error(message);
}

2.拦截器

@Autowired
StringRedisTemplate stringRedisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String token = request.getHeader("Authorization");if(token!=null&&token.contains("Bearer")){String tokenStr = token.substring(token.indexOf("Bearer") + 7);boolean verify = JwtUtils.verify(tokenStr);if(verify){//此处解析loginUsers,验证用户已登录Map<String, Object> claims = JwtUtils.getClaims(tokenStr);if(tokenStr.equals(stringRedisTemplate.opsForValue().get(claims.get("userId").toString()))){ThreadLocalUtil.set(claims);//用户信息放置ThreadLocalreturn true;};}}response.setStatus(HttpStatus.UNAUTHORIZED.value());response.setContentType("application/json;charset=UTF-8");ObjectMapper objectMapper = new ObjectMapper();objectMapper.writerFor(Result.class);String message = objectMapper.writeValueAsString(Result.error("token验证失败,请重新获取token后重试!"));response.getWriter().println(message);return false;
}

3. 登出

@RequestMapping("logout")
public Result logout(@Valid User loginUser,@RequestHeader("Authorization") String token){String message="用户名/密码不正确";User user = userSerivce.findUserByName(loginUser.getUsername());if(user!=null){//用户存在if(token!=null&&token.contains("Bearer")){String tokenStr = token.substring(token.indexOf("Bearer") + 7);boolean verify = JwtUtils.verify(tokenStr);if(verify&&tokenStr.equals(loginInceptor.get(user.getId()))){
//                    loginInceptor.remove(user.getId());stringRedisTemplate.delete(user.getId().toString());return Result.success("登出成功");}}}return Result.error(message);
}

4. 修改密码

@PatchMapping("updatePwd")public Result updatePwd(@RequestBody Map<String,String> params){String oldPwd = params.get("old_pwd");String newPwd = params.get("new_pwd");String conPwd = params.get("con_pwd");//参数校验if(!StringUtils.hasLength(oldPwd)||!StringUtils.hasLength(newPwd)||!StringUtils.hasLength(conPwd)){return Result.error("缺少必要的参数");}if(!validPwdLen(oldPwd)||!validPwdLen(newPwd)||!validPwdLen(conPwd)){return Result.error("密码为8-20位");}//密码匹配Map<String, Object> claims =ThreadLocalUtil.get();Integer userId = (Integer) claims.get("userId");User user = userSerivce.findUserById(userId);if(!Md5Util.getMD5String(oldPwd).equals(user.getPassword())){return Result.error("密码有误");}//新密码匹配if(!newPwd.equals(conPwd)){return Result.error("两次密码不匹配");}//新旧匹配if(newPwd.equals(oldPwd)){return Result.error("新旧密码不能相同");}user.setPassword(Md5Util.getMD5String(newPwd));int i = userSerivce.UpdateUser(user);if(i!=1){return Result.success("密码修改失败");}stringRedisTemplate.delete(user.getId().toString());return Result.success("密码修改成功");}

总结

回到顶部
更多关于redis内容请参考redis系列专栏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/847018.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录35期Day59-JavaScript(day58休息)

Day59题目 LeetCode503下一个更大元素 核心思想:和之前的下一个更高温度差不多,使用单调栈,只不过这个需要你循环查找,可以通过遍历两次数组实现 /*** param {number[]} nums* return {number[]}*/ var nextGreaterElements function(nums) {var len nums.lengthvar res …

低代码平台:打破数据孤岛的利器,推动企业数字化转型

随着数字化浪潮的汹涌而至&#xff0c;企业对于快速开发应用程序的需求变得日益迫切。在这样一个快速变化的时代&#xff0c;如何能够高效地开发并上线新的应用程序&#xff0c;以满足市场和客户的不断变化的需求&#xff0c;成为了企业面临的一大挑战。而低代码开发平台&#…

RSA密钥生成、加解密代码

背景介绍 RSA公钥加密算法是1977年由罗纳德李维斯特&#xff08;Ron Rivest&#xff09;、阿迪萨莫尔&#xff08;Adi Shamir&#xff09;和伦纳德阿德曼&#xff08;Leonard Adleman&#xff09;一起提出的。1987年首次公布&#xff0c;当时他们三人都在麻省理工学院工作。RSA…

强化学习(一) 基本概念和赌博机问题

文章目录 什么是强化学习强化学习的两个基本特征强化学习的其它特征强化学习不同于有监督学习强化学习不同于无监督学习强化学习不同于进化方法强化学习的独特挑战强化学习典例 强化学习的要素强化学习的适用范围强化学习学术主线解决强化学习问题的一般框架赌博机两个影响因素…

SiT : Self-supervised vision Transformer

从NLP Transformer中借鉴而来的视觉 Transformer 在使用大规模监督数据或某种形式的协同监督&#xff08;例如教师网络&#xff09;进行预训练时已被证明是有效的。这些经过监督预训练的视觉Transformer在下游任务中通过最小的改动就能取得出色的结果。 随着监督预训练&#x…

告别盲目推广!Xinstall二维码携参技术,让App运营更精准高效

在移动互联网时代&#xff0c;App推广和运营已成为每个开发者必须面对的重要任务。然而&#xff0c;如何精准地定位目标用户&#xff0c;提高转化率和用户留存率&#xff0c;成为了摆在每个开发者面前的难题。今天&#xff0c;我们就来谈谈如何通过Xinstall二维码携参技术&…

AzSubEnum:针对Azure服务的子域名枚举查询工具

关于AzSubEnum AzSubEnum是一款专门为Azure服务量身定制的子域名枚举查询工具&#xff0c;该工具旨在帮助广大研究人员仔细搜索和识别与各种Azure服务相关的子域名信息。 通过结合查询技术和语句&#xff0c;AzSubEnum能够深入分析Azure的域名架构&#xff0c;并系统地探测和收…

Python使用trule库画小猪佩奇

在这篇博客中&#xff0c;我将向大家展示如何使用Python的Turtle模块来绘制一个可爱的小猪佩奇。这个项目不仅可以帮助你熟悉Turtle绘图&#xff0c;还可以让你在编程的过程中享受到绘画的乐趣。 并非百分百原创&#xff0c;有部分参考其他博主&#xff0c;请理性对待&#xff…

小学数学出题器-Word插件-大珩助手

Word大珩助手是一款功能丰富的Office Word插件&#xff0c;旨在提高用户在处理文档时的效率。它具有多种实用的功能&#xff0c;能够帮助用户轻松修改、优化和管理Word文件&#xff0c;从而打造出专业而精美的文档。 【新功能】小学数学出题器 1、实现了难度设定&#xff1b;…

Vue.js 中的登录状态管理:使用计算属性避免重复登录20240531

Vue.js 中的登录状态管理&#xff1a;使用计算属性避免重复登录 在前端开发中&#xff0c;用户的登录状态管理是一个非常常见的需求。我们希望用户在成功登录后&#xff0c;即使刷新页面&#xff0c;也能够保持登录状态&#xff0c;而不需要再次登录。在 Vue.js 中&#xff0c…

MySQL之创建高性能的索引(九)

创建高性能的索引 使用索引扫描来做排序 MySQL有两种方式可以生成有序的结果:通过排序操作&#xff1b;或者按索引顺序扫描(MySQL有两种排序算法)&#xff1b;如果EXPLAIN出来的type列的值为"index"&#xff0c;则说明使用了索引扫描来做排序(不要和Extra列的"…

怎么控制员工电脑的文件外发,六个控制文件外发的小窍门你必须了解

控制员工电脑的文件外发是企业信息安全管理中的重要环节&#xff0c;旨在防止敏感数据泄露、保护知识产权和维护商业秘密。 企业可以通过多种技术和管理措施相结合的方式来达到这一目的&#xff0c;确保既有效控制文件外发风险&#xff0c;又不影响正常的业务运作和员工工作效…

排序题目:删除某些元素后的数组均值

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;删除某些元素后的数组均值 出处&#xff1a;1619. 删除某些元素后的数组均值 难度 2 级 题目描述 要求 给定一个整数数组 arr \texttt{arr} arr&…

文献阅读:GCNG:用于从空间转录组数据推断基因相互作用的图卷积网络

文献介绍 「文献题目」 GCNG: graph convolutional networks for inferring gene interaction from spatial transcriptomics data 「研究团队」 Ziv Bar-Joseph&#xff08;美国卡内基梅隆大学&#xff09; 「发表时间」 2020-12-10 「发表期刊」 Genome Biology 「影响因子…

python 贪心算法(Greedy Algo)

贪婪是一种算法范式&#xff0c;它逐步构建解决方案&#xff0c;始终选择提供最明显和直接收益的下一个部分。贪婪算法用于解决优化问题。 如果问题具有以下属性&#xff0c;则可以使用贪心法解决优化问题&#xff1a; 每一步&#xff0c;我们都可以做出当前看来最好的选择&…

Python模块之Pandas(三)-- DataFrame 查看形状和部分数据

查看数据框的形状&#xff1a; import pandas as pd data pd.read_csv("D:/my_data/data1.csv")print(data的形状为:, data.shape) 查看数据前10行&#xff1a; data.head(10) #查看数据前10行 查看数据后10行&#xff1a; data.tail(10) 查看数据某几列/某几…

3d网渲100比本地渲染快吗?渲染100邀请码1a12

3D网渲是一种基于云计算的技术&#xff0c;它将渲染工作交由云端进行&#xff0c;以网渲平台渲染100为例&#xff0c;比起本地渲染&#xff0c;它有以下一些优势。 1、本地渲染受硬件限制&#xff0c;只能一台电脑渲染一张图&#xff0c;而渲染100有充足的服务器数量&#xf…

Unity中的Surface Effector 2D组件

Surface Effector 2D 是 Unity 中 2D 物理引擎提供的一个组件&#xff0c;用于影响与其接触的 2D 对象的运动。它可以对碰撞到其表面的物体施加速度和力&#xff0c;从而改变这些物体的运动行为。下面是一些关于 Surface Effector 2D 的关键点&#xff1a; 主要属性 Speed&am…

QT 音乐播放器【一】 显示音频级别指示器

文章目录 效果图概述代码总结 效果图 概述 QMediaPlayer就不介绍了&#xff0c;就提供了一个用于播放音频和视频的媒体播放器 QAudioProbe 它提供了一个探针&#xff0c;用于监控音频流。当音频流被捕获或播放时&#xff0c;QAudioProbe 可以接收到音频数据。这个类在需要访问…

如何选择采购管理软件解决方案:推荐与指南

选择一款合适自身企业采购模式的管理软件对于企业来说至关重要。一款好的采购管理软件不仅能够提高采购效率&#xff0c;还能降低采购成本、优化库存管理、增强供应链的透明度和可控性。而在选择采购管理软件时&#xff0c;大家还需要考虑以下几个关键因素&#xff1a; 一、需…