您的位置:首页 > 汽车 > 新车 > 福州便民网首页_拓者设计室内设计官网首页_软文发布软件_淘特app推广代理

福州便民网首页_拓者设计室内设计官网首页_软文发布软件_淘特app推广代理

2025/5/2 18:12:05 来源:https://blog.csdn.net/qq_73595043/article/details/147373571  浏览:    关键词:福州便民网首页_拓者设计室内设计官网首页_软文发布软件_淘特app推广代理
福州便民网首页_拓者设计室内设计官网首页_软文发布软件_淘特app推广代理

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的配置文件指定对应的配置信息

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com