【第5章】SpringBoot实战篇之登录模式切换

文章目录

  • 前言
  • 一、接口扩展
    • 1. LoginStorage
    • 2. LocalLoginStorage
    • 3. RedisLoginStorage
    • 4. 参数配置
  • 二、登录相关接口改动
    • 1.登录接口
    • 2. 登录拦截器
  • 总结


前言

前面分别介绍了本地Map和redis存储用户登录信息,但是第二天我登录就出现问题了,因为我Redis部署在虚拟机里面,不可能每次都专门启动虚拟机,来回替换代码也太麻烦,这里我们根据配置参数来控制下将用户信息存储到哪里。


一、接口扩展

开放扩展,关闭修改。

1. LoginStorage

package org.example.springboot3.bigevent.login;/*** Create by zjg on 2024/6/3*/
public interface LoginStorage {public void put(String id, String token);public String get(String id);public boolean remove(String id);
}

2. LocalLoginStorage

package org.example.springboot3.bigevent.login;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** Create by zjg on 2024/6/3*/
@ConditionalOnProperty(name="login.storage",havingValue = "0")
@Component
public class LocalLoginStorage implements LoginStorage{private Map<String,String> loginUsers=new ConcurrentHashMap<>(256);@Overridepublic void put(String id, String token) {loginUsers.put(id, token);}@Overridepublic String get(String id) {return loginUsers.get(id);}@Overridepublic boolean remove(String id) {return loginUsers.remove(id)!=null;}}

3. RedisLoginStorage

package org.example.springboot3.bigevent.login;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;/*** Create by zjg on 2024/6/3*/
@ConditionalOnProperty(name="login.storage",havingValue = "1")
@Component
public class RedisLoginStorage implements LoginStorage{@AutowiredStringRedisTemplate stringRedisTemplate;@Overridepublic void put(String id, String token) {stringRedisTemplate.opsForValue().set(id,token,24, TimeUnit.HOURS);}@Overridepublic String get(String id) {return stringRedisTemplate.opsForValue().get(id);}@Overridepublic boolean remove(String id) {return Boolean.TRUE.equals(stringRedisTemplate.delete(id));}
}

4. 参数配置

这个参数控制使用本地存储、还是redis存储,这样扩展起来也方便。

login:storage: 0

二、登录相关接口改动

1.登录接口

@Autowired
LoginStorage loginStorage;
@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);loginStorage.put(user.getId().toString(),token);return Result.success("登录成功",token);}}return Result.error(message);
}

2. 登录拦截器

@Autowired
LoginStorage loginStorage;
@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(loginStorage.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;
}

总结

回到顶部

这样我们就可以通过参数login.storage的修改,灵活地调整用户登录信息的存储方式了。
后面的登出接口和修改密码接口也会涉及到模式的使用。

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

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

相关文章

QT4-QT5升级(3)GBK-UTF-8-乱码“常量中有换行符”

乱码有两种&#xff1a;我命名为汉字乱码菱形乱码如下&#xff1a; 1.文件编码为&#xff1a; GB2312 打开编码&#xff1a; GB2312 编译后&#xff1a; QString 部分字符串 常量中有换行符 char * …

论文阅读- CycleFormer : TSP Solver Based on Language Modeling

Q: 这篇论文试图解决什么问题&#xff1f; A: 这篇论文提出了一个新的基于Transformer模型的旅行商问题&#xff08;Traveling Salesman Problem, TSP&#xff09;求解器&#xff0c;称为CycleFormer。它旨在解决传统Transformer模型在应用于TSP时面临的一些挑战和局限性&…

JavaScript 函数调用

JavaScript 函数调用 函数是 JavaScript 编程语言的核心组成部分&#xff0c;它们允许开发者将代码组织成可重用的块。在 JavaScript 中&#xff0c;函数调用是执行函数代码的方式。本文将深入探讨 JavaScript 中的函数调用&#xff0c;包括基本语法、不同类型的函数调用方式&…

RocketMq源码解析五:生产者Producer发送消息

上一章我们把生产者启动的流程和大家一起跟着源码走了一遍,现在我们来看发送消息的流程。上一章我们已经把核心接口和类关系梳理了一遍。如下图 我们今天重点看MQProducer中的send方法最终的实现。DefaultMQProducer中,send的实现最终还是调用了 defaultMQProducerIm…

有问有答—JavaSE—反射应用

写一个函数&#xff0c;传入任意的对象&#xff0c;可以将对象里面String类型的属性中的a改成b。 field.getClass() private void changeField(Object object) throws IllegalAccessException {//1.获得对应的字节码Class clazz object.getClass();//对象.getClass。 类.cla…

Openfeign远程调用

在实际开发中&#xff0c;Openfeign远程调用要避免在循环中使用&#xff0c;这个是比较耗时的。如使用不当可能会把远程服务压垮。正确的用法是在循环外一次查询获得条件的Map集合&#xff0c;然后在循环里边通过给map传入key&#xff0c;从而获得map对应的值&#xff0c;从而避…

微信小程序-案例:本地生活-首页(不使用网络数据请求)

一、 1.页面效果&#xff1a; 二、 1.新建项目并添加页面 在app.json文件中&#xff1a; "pages": ["pages/home/home","pages/message/message","pages/contact/contact"] 2.配置导航栏效果 在app.json文件中&#xff1a; &quo…

yolov8-obb 旋转目标检测 瑞芯微RKNN芯片部署、地平线Horizon芯片部署、TensorRT部署

特别说明&#xff1a;参考官方开源的yolov8代码、瑞芯微官方文档、地平线的官方文档&#xff0c;如有侵权告知删&#xff0c;谢谢。 模型和完整仿真测试代码&#xff0c;放在github上参考链接 模型和代码。 折腾旋转目标检测的小伙伴们看过来&#xff0c;yolov8旋转目标检测部署…

力扣 41.缺少的第一个正整数

题目描述&#xff1a; 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 解释&#xff1a;范围 …

【文末附gpt升级秘笈】Fast-DetectGPT:机器生成文本与人类撰写文本的区别检测研究

Fast-DetectGPT&#xff1a;机器生成文本与人类撰写文本的区别检测研究 摘要&#xff1a; 近年来&#xff0c;随着人工智能技术的飞速发展&#xff0c;机器生成文本的质量日益提高&#xff0c;使得区分机器生成文本与人类撰写文本成为了一个挑战。西湖大学张岳教授团队近期在这…

趣测小程序开发搭建,趣测趣玩小程序是何物?

一、趣测小程序简介 趣测趣玩小程序是一款提供趣味测试和玩乐功能的应用程序。用户可以通过该小程序参与各种有趣的测试&#xff0c;这些测试可能涵盖性格、情感、智力等多个方面&#xff0c;旨在为用户提供轻松愉快的体验。同时&#xff0c;该小程序还可能包含一些游戏元素&a…

8086 汇编笔记(十):标志寄存器

前言 一、ZF 标志 Zero Flag&#xff0c;零标记位。用于记录相关指令执行后&#xff0c;其结果是否为 0。如果结果为 0&#xff0c;则 ZF1&#xff0c;如果结果非 0&#xff0c;则 ZF0 mov ax,1 sub ax,1 ;ZF 1 mov ax,2 sub ax,1 ;ZF0 二、PF 标志 Parity Flag&a…

AutoCAD记录

esc&#xff1a;取消&#xff08;取消操作&#xff09; L空格&#xff1a;画直线 C空格&#xff1a;画圆 &#xff08;软件提供了圆的多种画法&#xff0c;其中包括与其他图形的切线&#xff09; A空格&#xff1a;画圆弧 tab&#xff1a;切换数据输入框&#xff08;如下图…

安卓手机APP开发_____通过设备管理政策增强安全性

安卓手机APP开发_____通过设备管理政策增强安全性 目录 概述 定义并声明政策 创建设备管理接收器 激活设备管理器 实现设备政策控制器 概述 设备管理弃用。部分管理员政策在由设备管理员调用时被标记为已弃用。 如需了解详情并查看迁移选项&#xff0c;请参阅 设备管理弃…

等保测评3级-技术测评要求 上

技术测评要求(S3A3G3) 等保测评3级技术评测要求 等级保护三级技术类测评控制点(S3A3G3)类别 序号 10. 11. 12. 13. 防雷 击 14. 15. 16. 防火 17. 18. 19. 防水 和防 潮 20. 21. 22. 测 评 内 容 应对介质分类标识&#xff0c; 存储在介质库或档案室中。 (G2) 应利用光、电等…

Renesas MCU之串口的发送接收功能实现

目录 概述 1 软硬件介绍 1.1 软件版本信息 1.2 硬件介绍 2 FSP配置项目 2.1 项目参数配置 2.2 配置UART参数 3 功能实现 3.1 软件架构实现 3.2 UART接口函数 3.2.1 R_SCI_UART_Open() 3.2.2 R_SCI_UART_Close() 3.2.3 R_SCI_UART_Read() 3.2.4 R_SCI_UART_Writ…

java自学阶段二:JavaWeb开发50(Spring和Springboot学习)

Spring、Springboot基础知识学习 目录 学习目标Spring基础概念IOC控制反转DI依赖注入事务管理AOP面向切面编程Spring案例说明&#xff08;Postman使用、Restful开发规范、lombok、Restful、nginx了解&#xff09; 一&#xff1a;学习目标&#xff1a; 1&#xff09;了解Sprin…

如何解决chatgpt出现503 bad gateway的问题

昨日&#xff0c;ChatGPT官网挂了&#xff0c;也就是使用web网页端访问的用户&#xff0c;会出现 bad gateway 情况。我们去ChatGPT官方的监控查看&#xff0c;已经展示相关错误。 影响的范围有&#xff1a; 影响了 ChatGPT 所有计划的所有用户。影响包括所有与 ChatGPT 相关…

Spring ApplicationContext的getBean方法

Spring ApplicationContext的getBean方法 在Spring框架的ApplicationContext中&#xff0c;getBean(Class<T> requiredType)方法可以接受一个类类型参数&#xff0c;这个参数可以是接口类也可以是实现类。 使用接口类&#xff1a; 如果requiredType是一个接口&#xff0c…

React:Expected property name or ‘}‘ in JSON at position 1

代码&#xff1a; import { Form, Input, Button } from antd export default function FormCom() {function onFinish(a, b, c, d) {console.log(a, b, c, d)}const describe "{tip:请输入用户名}"return (<><Form onFinish{onFinish}><Form.Itemn…