当前位置: 首页 > news >正文

SpringBoot实战4

SpringBoot实战4


一、优化登录机制通过Redis

在我们使用JWT令牌进行登录验证的时候,不可避免的也会出现一些问题。比如:当用户修改密码后,旧的令牌仍然生效,任然可以用于进行登录操作。因此,我们可以采用**Redis**进行登录的优化。


SpringBoot集成Redis

1、导入Redis起步依赖

2、在yml配置文件中配置Redis的连接信息

3、调用API完成字符串的存取操作

<!--导入Redis的起步依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

yml

spring:data:redis:host: localhostport: 6379
@SpringBootTest//如果说在测试类上面添加了这个注解,那么在单元测试方法之前会先初始化Spring容器,这样就可以获取到IOC容器中的bean对象
public class RedisTest {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void testSet(){//网Redis中存储一个键值对ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.set("name","zhangsan");operations.set("id","1",15, TimeUnit.SECONDS);}@Testpublic void testGet(){//从Redis中获取一个键值对ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();String name = operations.get("name");System.out.println(name);}
}

登录优化

实现方法步骤

  1. 登录成功的时候,给浏览器响应令牌的同时,将对应的用户信息的令牌存入Redis中

    // 登录成功 Map<String,Object> claims=new HashMap<>(); claims.put("id",loginUser.getId()); claims.put("username",loginUser.getUsername()); String token = JwtUtil.genToken(claims); //把token存储在Redis中 ValueOperations<String, String> operations = stringRedisTemplate.opsForValue(); operations.set(token,token,12, TimeUnit.HOURS);

    //TODO: 登录
    @PostMapping("/login")
    public Result<String> login(@Pattern(regexp = "^\\S{5,16}$") String username,@Pattern(regexp = "^\\S{5,16}$") String password) {// TODO: 查询用户是否存在User loginUser = userService.findByUserName(username);// TODO: 判断用户是否存在if(loginUser==null){return Result.error("用户不存在");}// TODO: 判断密码是否正确else{if(Md5Util.getMD5String(password).equals(loginUser.getPassword())){// 登录成功Map<String,Object> claims=new HashMap<>();claims.put("id",loginUser.getId());claims.put("username",loginUser.getUsername());String token = JwtUtil.genToken(claims);//把token存储在Redis中ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.set(token,token,12, TimeUnit.HOURS);return Result.success(token);}else {return Result.error("密码错误");}}
    }
    
  2. LoginInterceptor拦截器中,需要验证浏览器携带的令牌,同时需要获取到Redis中存储与之对应的相同的令牌

    //从Redis中获取相同的token ValueOperations<String, String> operations = stringRedisTemplate.opsForValue(); String redisToken = operations.get(token); if (redisToken == null){ //redis中的token已经失效 throw new RuntimeException("token已失效"); }

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//在这个拦截器中验证Token---》通过请求头中携带的的tokenString token = request.getHeader("Authorization");//解析Tokentry {//从Redis中获取相同的tokenValueOperations<String, String> operations = stringRedisTemplate.opsForValue();String redisToken = operations.get(token);if (redisToken == null){//redis中的token已经失效throw new RuntimeException("token已失效");}Map<String, Object> claims = JwtUtil.parseToken(token);//TODO:将相关的业务数据存到ThreadLocal中-->方便后续业务逻辑中获取ThreadLocalUtil.set(claims);//TODO:如果解析成功,则放行return true;} catch (Exception e) {response.setStatus(401);//TODO:如果解析失败,则返回错误信息,并且拦截return false;}
    }
    
  3. 修改密码的时候就删除旧的令牌

    //删除Redis中对应的token ValueOperations<String, String> operations = stringRedisTemplate.opsForValue(); RedisOperations<String, String> redisOperations = operations.getOperations(); redisOperations.delete(token);

    // TODO: 更新用户的密码
    @PatchMapping("/updatePwd")
    public Result updatePwd(@RequestBody Map<String,String> params,@RequestHeader("Authorization") String token){//1、校验参数String oldPwd = params.get("old_pwd");String newPwd = params.get("new_pwd");String rePwd = params.get("re_pwd");//判断只要有一个为空就返回错误信息if(oldPwd==null||newPwd==null||rePwd==null){return Result.error("参数不能为空");}//判断原密码是否正确---》调用Service根据用户名获取原密码,和oldPwd进行比较//用户名通过ThreadLocalUtil存储获取Map<String,Object> map = ThreadLocalUtil.get();String username = (String) map.get("username");User user = userService.findByUserName(username);String pwd = user.getPassword();//原有的密码是进行了加密的,所以需要先对用户输入的密码进行加密再进行比较if(!Md5Util.getMD5String(oldPwd).equals(pwd)){return Result.error("原密码错误");}//判断新密码和确认密码是否一致if(!newPwd.equals(rePwd)){return Result.error("新密码和确认密码不一致");}//2、调用Service完成更新密码userService.updatePwd(newPwd);//删除Redis中对应的tokenValueOperations<String, String> operations = stringRedisTemplate.opsForValue();RedisOperations<String, String> redisOperations = operations.getOperations();redisOperations.delete(token);return Result.success();
    }
    
  4. 拦截器中进行再次校验


项目部署

打成jar包,引入依赖,并通过Maven的package进行打包

<build><plugins><!--配置打包插件--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>3.4.4</version></plugin></plugins>
</build>

得到的jar包

在对应的目录下打开cmd命令行窗口

执行java -jar big-event-1.0-SNAPSHOT.jar(输入了java -jar之后按
Tab键自动补全)


SpringBoot属性配置(三种方式的优先级从低到高)

1、通过properties或者yml

2、命令行中进行修改(–键=值)

java -jar big-event-1.0-SNAPSHOT.jar --server.port=9090

3、通过在jar包目录下加上一个application.yml的配置文件指定对应的配置信息

http://www.xdnf.cn/news/45397.html

相关文章:

  • chili3d调试6 添加左侧面板
  • Linux学习——了解和熟悉Linux系统的远程终端登录
  • 架构师面试(三十四):IM 假在线
  • Qt中修改了UI设计文件后编译不生效问题的解决办法
  • 基于若依开发公网访问项目
  • 精益数据分析(8/126):从Airbnb案例看精益创业与数据驱动增长
  • 数据通信学习笔记之OSPF的区域
  • 学习笔记—C++—string(一)
  • 2025年渗透测试面试题总结-拷打题库07(题目+回答)
  • SQL之DML(查询语句:select、where)
  • Mysql insert一条数据的详细过程
  • [SpringBoot-1] 概述和快速入门(使用vscode)
  • 在阿里云和树莓派上编写一个守护进程程序
  • 数据分析师-Part1-职业介绍
  • 每天学一个 Linux 命令(26):less
  • Vue3 响应式原理: Proxy 数据劫持详解
  • Oracle高级语法篇 - 用户与角色关系
  • 从零创建 Docker 镜像
  • DeepSeek与ECharts融合助力复杂图表高效制作
  • Python网络爬虫设计(三)
  • python生成项目依赖文件requirements.txt
  • 计算机组成与体系结构:计算机结构的分类(classifications of computer architecture)
  • 牛客 | OJ在线编程常见输入输出练习
  • Towards Transferable Targeted 3D Adversarial Attack in the Physical World--阅读笔记
  • 深度解析 PointNet:点云深度学习的开山之作
  • 低代码开发平台:企业数字化转型的加速器
  • MCU中的BSS和data都占用SRAM空间吗?
  • LeetCode hot 100—分割等和子集
  • JavaWeb 课堂笔记 —— 15 MyBatis 基础操作
  • 【2】Kubernetes 架构总览