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

【第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的修改,灵活地调整用户登录信息的存储方式了。
后面的登出接口和修改密码接口也会涉及到模式的使用。

相关文章:

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

文章目录 前言一、接口扩展1. LoginStorage2. LocalLoginStorage3. RedisLoginStorage4. 参数配置 二、登录相关接口改动1.登录接口2. 登录拦截器 总结 前言 前面分别介绍了本地Map和redis存储用户登录信息&#xff0c;但是第二天我登录就出现问题了&#xff0c;因为我Redis部…...

2024最新华为OD算法题目

在一个机房中,服务器的位置标识在 n*m 的整数矩阵网格中,1表示单元格上有服务器,0 表示没有。如果两台服务器位于同一行或者同一列中紧邻的位置,则认为它们之间可以组成一个局域网。请你统计机房中最大的局域网包含的服务器个数。 输入描述 第一行输入两个正整数,n和m,…...

Redis集群方案有哪些?

今天咱们来聊聊Redis集群方案&#xff0c;想象一下Redis是个超级大的储物柜&#xff0c;里面放满了你各种各样的宝贝&#xff08;数据&#xff09;。但随着宝贝越来越多&#xff0c;一个储物柜不够用了&#xff0c;这时候我们就得想方设法扩大空间&#xff0c;还要保证找东西依…...

数字影像产业园的三大赋能:科技、创新与无限可能

数字影像产业园作为文创产业的重要载体&#xff0c;以科技为核心驱动力&#xff0c;不断推动产业的技术革新和升级。 园区内汇聚了最前沿的数字技术资源&#xff0c;高清摄影设备、虚拟现实技术、人工智能应用等尖端科技在这里得到广泛应用&#xff0c;不仅提升了生产效率&…...

枚举(enum)+联合体(union)

枚举联合 一.枚举类型1.枚举类型的声明2.枚举类型的优点3.枚举类型的使用 二.联合体1.联合体类型的声明2.联合体的特点3.相同成员的结构体和联合体对比4.联合体大小的计算5.联合体的练习&#xff08;判断大小端&#xff09;6.联合体节省空间例题 一.枚举类型 1.枚举类型的声明…...

postman教程-15-前置脚本

上一小节我们学习了Postman生成随机数的方法&#xff0c;本小节我们讲解一下Postman前置脚本的使用方法。 Postman中的前置脚本&#xff08;Pre-request Script&#xff09;允许你在发送请求之前运行JavaScript代码。这可以用于修改请求头、查询参数、请求体等&#xff0c;或者…...

AIGC会带来失业潮吗?紧紧跟时代第一步,如何学习AIGC

会&#xff0c;但AI淘汰的始终是跟不上时代的人。 现在很多公司都有AI培训&#xff0c;不仅GPT&#xff0c;还有Midjourney、Stable DIffusion等一系列AI工具。 像我们公司虽然今年招的少&#xff0c;但也会对新招的应届生统一进行AI培训。 用任正非先生的话来说就是&#x…...

C++第二十四弹---从零开始模拟STL中的list(上)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、基本结构 2、基本函数实现 2.1、默认构造函数 2.2、尾插数据 3、迭代器的封装 3.1、迭代器的基本结构 3.2、迭代器重载函数的实现 4、迭…...

大宋咨询(深圳社情民意调查)关于社情民意调查研究的内容

社情民意调查内容&#xff0c;是一项至关重要的社会研究活动&#xff0c;它涵盖了社会生活的方方面面&#xff0c;通过深入了解民众的需求、态度和看法&#xff0c;为决策提供了宝贵的参考依据。 首先&#xff0c;社会经济状况是社情民意调查不可或缺的一部分。这包括了对当地…...

PID算法在电机速度控制上的应用

目录 概述 1 系统硬件框架 1.1 框架介绍 1.2 硬件实物图 2 STM32Cub生成工程 2.1 软件版本信息 2.2 配置参数 ​编辑2.3 生成项目 3 PID算法实现 3.1 概念 3.2 代码实现 4 其他功能实现 4.1 设置电机速度 4.2 PID算法控制电机 4.3 功能函数的调用 5 测试 5.1 …...

埃隆·马斯克 - 从梦想家到改变世界的企业家

埃隆马斯克 - 从梦想家到改变世界的企业家 本文内容是埃隆马斯克传的重点章节精华提炼&#xff0c;介绍了马斯克传奇一生 参考资料内容&#xff1a;埃隆马斯克传&造梦者埃隆马斯克 参考资料在文末获取&#xff0c;关注我&#xff0c;分享优质前沿资料&#xff08;IT、运…...

微信小程序长图片自适应

/*wxss中的代码*/ .image-container { display:flex;width: 100%; /* 或其他需要的宽度 */ /* margin-bottom: 10px; //图片之间的间距 */height: auto; } 核心&#xff1a;要真正自适应&#xff0c;就要在wxml中加入固定宽度style“width:750rpx” /*wxml中的代码*/ &l…...

elasticsearch hanlp 插件安装操作

elasticsearch hanlp 插件安装操作 下载 hanlp 插件上传hanlp插件到elasticsearch服务器安装hanlp插件kibana测试 下载 hanlp 插件 这里大家根据自己对应的 elasticsearch 版本下载匹配版本的 hanlp 插件&#xff0c;由于 hanlp 及 elasticsearch 各个版本之间差别较大&#x…...

为什么进程和线程 ID 总是 4 的倍数?

如果您研究下任务管理器中的的进程 ID (PID)&#xff0c;则你会发现这样一个规律&#xff1a;它们都是 4 的倍数。 基于 Windows NT 内核的操作系统上&#xff0c;不止是进程 ID&#xff0c;实际上&#xff0c;线程 ID (TID) 也遵守这样的规律&#xff1a;也即它们都是 4 的倍…...

LabVIEW版本控制

LabVIEW作为一种流行的图形化编程环境&#xff0c;在软件开发中广泛应用。有效地管理版本控制对于确保软件的可靠性和可维护性至关重要。LabVIEW提供了多种方式来管理VI和应用程序的修订历史&#xff0c;以满足不同规模和复杂度的项目需求。 LabVIEW中的VI修订历史 LabVIEW内置…...

不输Kimi的AI插件——Elmo Chat (免费,无需注册)

&#x1f31a; 前阵子不是写了篇《一分钟上手AI神器——Kimi (附_ 官方提示词)》 嘛&#xff0c;给大伙安利了一波 Kimi Chat 这个AI 神器&#xff0c;不知道是不是用户量上来了&#xff0c;算力一下子跟不上&#xff0c;感觉变笨了不少&#x1f923;。在别的推文看到多轮对话后…...

使用cesiumLab使shp转为3dtlies

过程不做赘述&#xff0c;网上大把&#xff0c;说下注意事项。 1. 存储3DTiles 选项 若是打开则输出的文件为glb格式文件,因为glb文件好储存易传输跨平台。cesium可以使用但无法处理&#xff0c;例如改变颜色&#xff0c;改着色器等。若是不打开则输出的文件为bm3d格式文件,此…...

中科数安 | 透明加密防泄密系统!如何有效防止企业内部核心数据资料外泄?

中科数安提供的透明加密防泄密系统是一种专为企业设计的数据保护解决方案&#xff0c;它通过以下关键特性有效防止企业内部核心数据资料外泄&#xff1a; PC地址&#xff1a;——www.weaem.com 自动智能透明加密&#xff1a;系统能够在操作系统级别无缝集成&#xff0c;对指定类…...

go的反射和断言

在go中对于一个变量&#xff0c;主要包含两个信息变量类型&#xff08;type&#xff09;和变量值&#xff08;value&#xff09; 可以通过reflect包在运行的时候动态获取变量信息&#xff0c;并能够进行操作 对于Type可以通过reflect.TypeOf()获取到变量的类型信息 reflect.Ty…...

打造新引擎,迈向数智金融新未来

数智技术正在全面赋能金融机构转型升级以及促进金融与实体经济的加速融合&#xff0c;已呈现出金融机构数智化经营加速、产业 数字金融深度融合、数字技术驱动绿色金融发展、金融信创成果涌现、金融机构加快数字化组织管理变革等行业趋势。 根据银行业协会调研&#xff0c;78%…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...