后台管理系统登录业务分析(图片验证码登录)

文章目录

  • 1、登录业务分析
  • 2、登录开发流程
    • 2.1、获取图片验证码接口业务
    • 2.2、CodeImgServiceImpl
      • 2.2.1、响应
    • 2.3、IndexController
    • 2.4、SysUserServiceImpl
    • 2.5、SysUserMapper.xml
  • 3、springmvc拦截器创建&注册
    • 3.1、springmvc拦截器的创建
    • 3.2、springmvc拦截器注册
    • 3.3、SysUserServiceImpl

1、登录业务分析

在这里插入图片描述

2、登录开发流程

在这里插入图片描述

2.1、获取图片验证码接口业务

    @GetMapping("codeImg")public Result generateCodeImg() {Map<String, String> map = codeImgService.generateCodeImg();return Result.ok(map);}

2.2、CodeImgServiceImpl

package com.atguigu.spzx.manager.service.impl;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.core.util.IdUtil;
import com.atguigu.spzx.manager.service.CodeImgService;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Service
public class CodeImgServiceImpl implements CodeImgService {@ResourceStringRedisTemplate stringRedisTemplate;/*** 生成圆形验证码的图片和验证码字符串,并将其存储在Redis中以供后续验证使用。* 验证码图片以Base64编码的形式返回,同时返回验证码在Redis中的键值。** @return 包含验证码键和Base64编码的验证码图片的映射。*/@Overridepublic Map<String, String> generateCodeImg() {// 创建一个圆形验证码对象,参数分别为图片宽度、高度、验证码长度和干扰线数量。CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20);// 获取生成的验证码字符串。String code = captcha.getCode();// 生成一个唯一的键值用于在Redis中存储验证码,键的格式为"sys:user:code:唯一ID"。//1、缓存到redis中String key = "sys:user:code:" + IdUtil.getSnowflake(1, 1).nextIdStr();// 将验证码存储在Redis中,过期时间为10分钟。stringRedisTemplate.opsForValue().set(key, code, 10, TimeUnit.MINUTES);// 获取验证码图片的Base64编码。//2、响应给前端:codeImg的base64字符串String codeImg = captcha.getImageBase64();// 创建一个映射,用于存储验证码的键和Base64编码的图片。HashMap<String, String> map = new HashMap<>();// 将验证码键和Base64编码的图片添加到映射中。map.put("codeKey", key);map.put("codeImg", "data:img/png;base64," + codeImg);// 返回映射。return map;}}

在这里插入图片描述

在这里插入图片描述

2.2.1、响应

{"code": 200,"message": "SUCCESS","data": {"codeKey": "sys:user:code:1801531733133365248","codeImg": "data:img/png;base64,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"}
}

2.3、IndexController

    @PostMapping("/login")public Result login(@RequestBody LoginDto loginDto) {LoginVo loginVo = sysUserService.login(loginDto);return Result.ok(loginVo);}

2.4、SysUserServiceImpl

    /*** 用户登录方法** @param loginDto 登录请求对象,包含用户名、密码、验证码等信息* @return 登录成功返回登录信息对象,包含令牌(token)等信息* @throws SpzxException 如果登录参数错误、用户名不存在、验证码错误或密码错误,则抛出异常*/@Overridepublic LoginVo login(LoginDto loginDto) {// 获取登录请求中的用户名、密码、验证码和验证码键String userName = loginDto.getUserName();String password = loginDto.getPassword();String code = loginDto.getCode();String codeKey = loginDto.getCodeKey();// 检查登录参数是否为空,如果为空则抛出参数错误异常if (StringUtils.isEmpty(userName)|| StringUtils.isEmpty(password)|| StringUtils.isEmpty(code)|| StringUtils.isEmpty(codeKey)) {throw new SpzxException(ResultCodeEnum.LOGIN_PARAMS_ERROR);}// 根据用户名查询系统用户信息SysUser sysUser=sysUserMapper.findSysUserByUsername(userName);// 如果用户不存在,则抛出用户名错误异常if (sysUser == null) {throw new SpzxException(ResultCodeEnum.LOGIN_USERNAME_ERROR);}// 验证验证码,如果验证码不存在或不匹配,则抛出验证码错误异常// 校验验证码String cachedCode = stringRedisTemplate.opsForValue().get(codeKey);if (StringUtils.isEmpty(cachedCode) || !code.equals(cachedCode)) {throw new SpzxException(ResultCodeEnum.LOGIN_CODE_ERROR);}// 验证密码,如果密码不匹配,则抛出密码错误异常String encodedPwd = sysUser.getPassword();// 前端传入的加密和数据库的密文比较:md5 相同的明文加密的结果一定相同(不可逆加密) 加盐加密String inputPwd = DigestUtils.md5DigestAsHex(password.getBytes());if (!inputPwd.equals(encodedPwd)) {throw new SpzxException(ResultCodeEnum.LOGIN_PASSWORD_ERROR);}// 删除已使用的验证码stringRedisTemplate.delete(SpzxConst.LOGIN_USER_CODE_PREFIX + codeKey);// 生成新的令牌,并将用户信息(脱敏处理,不包含密码)缓存起来// 缓存登录状态sysUser.setPassword(null);//脱敏  清空敏感数据String json = JSON.toJSONString(sysUser);//IdUtil提供的雪花算法id长度为19位   由10进制数字组成  按照时间递增 的唯一idString token = IdUtil.getSnowflake(1, 1).nextIdStr();stringRedisTemplate.opsForValue().set(SpzxConst.LOGIN_USER_KEY_PREFIX + token, json, 7, TimeUnit.DAYS);// 构建并返回登录信息对象LoginVo loginVo = new LoginVo();loginVo.setToken(token);    // 只返回了token   redis查询数据时需要和前缀字符串拼接才可以loginVo.setRefresh_token("111111");return loginVo;}

2.5、SysUserMapper.xml

    <select id="findSysUserByUsername" resultType="com.atguigu.spzx.model.entity.sys.SysUser">select id,username, password, name,phone,avatar, description,status, create_time, update_time, is_deleted as deletedfrom sys_userwhere username = #{username} and is_deleted=0;</select>

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

{"code": 200,"message": "SUCCESS","data": {"token": "1801532558987628544","refresh_token": "111111"}
}

3、springmvc拦截器创建&注册

  1. springmvc拦截器 登录验证&放行首页请求
  2. springmvc拦截器 预检请求放行
  3. springmvc拦截器 使用CurrentHashMap透传登录状态
  4. springmvc拦截器 ThreadLocal透传数据

在这里插入图片描述

3.1、springmvc拦截器的创建

package com.atguigu.spzx.manager.interceptor;
import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.common.handler.exception.SpzxException;
import com.atguigu.spzx.common.util.consts.SpzxConst;
import com.atguigu.spzx.common.util.utils.ThreadLocalUtil;
import com.atguigu.spzx.model.entity.sys.SysUser;
import com.atguigu.spzx.model.result.ResultCodeEnum;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
@Component
public class SpzxLoginAuthInterceptor implements HandlerInterceptor {@Resourceprivate StringRedisTemplate stringRedisTemplate;//ThreadLocal:线程本地变量(每个线程对象的成员变量都是私有的,其他线程不能访问)//Map共享登录状态数据 透传给后续的业务使用//键:使用当前线程对象      值:使用SysUser对象//ConcurrentHashMap性能比Hashtable好,但是仍然存在并发竞争//public static ConcurrentHashMap<Thread, SysUser> SYS_USERS_MAP=new ConcurrentHashMap();public static ThreadLocal<SysUser> THREAD_LOCAL=new ThreadLocal<>();@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//区分是预检还是正常请求,正常请求进行登录校验//预检请求直接放行String method = request.getMethod();if ("OPTIONS".equals(method.toUpperCase())) {return true;}String token = request.getHeader("token");if (StringUtils.isEmpty(token)) {throw new SpzxException(ResultCodeEnum.LOGIN_STATUS_ERROR);}String json = stringRedisTemplate.opsForValue().get(SpzxConst.LOGIN_USER_KEY_PREFIX + token);if (StringUtils.isEmpty(json)) {throw new SpzxException(ResultCodeEnum.LOGIN_STATUS_ERROR);}//缓存登录状态共享给后续的业务使用//request域共享数据//也可以使用内存共享数据:Map<String,SysUser>  ConcurrentHashMap<String,SysUser>//token:每个用户唯一的登录状态token,但是后面获取map中的数据时还需要token然后再查询数据//Thread.currentThread();    当前线程对象//SYS_USERS_MAP.put(Thread.currentThread(), JSON.parseObject(json, SysUser.class));//使用线程对象的threadLocalMap存储:key为THREAD_LOCAL对象,值为传入的数据THREAD_LOCAL.set(JSON.parseObject(json, SysUser.class));ThreadLocalUtil.setSysUser(JSON.parseObject(json, SysUser.class));return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//清空不在使用的登录缓存//SYS_USERS_MAP.remove(Thread.currentThread());THREAD_LOCAL.remove();ThreadLocalUtil.remove();}
}

3.2、springmvc拦截器注册

package com.atguigu.spzx.manager.interceptor;
import com.atguigu.spzx.manager.util.SpzxLoginAuthProperties;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class SpzxWebMvcConfigurer implements WebMvcConfigurer {@Resourceprivate SpzxLoginAuthInterceptor spzxLoginAuthInterceptor;@Resourceprivate SpzxLoginAuthProperties spzxLoginAuthProperties;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(spzxLoginAuthInterceptor).addPathPatterns("/**").excludePathPatterns(spzxLoginAuthProperties.getWhiteUrls());}// 配置全局跨域访问@Override/*该代码是一个Java文件,文件名为SpzxWebMvcConfigurer.java。该代码是一个全局跨域配置器,用于允许跨域请求。通过调用addCorsMappings方法,将全局跨域映射添加到CorsRegistry中。映射路径为"/**",允许所有请求头、所有请求方法和所有源域。此外,还允许凭证请求。*/public void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**")  // 添加全局跨域映射.allowedHeaders("*")  // 允许所有请求头.allowedMethods("*")  // 允许所有请求方法.allowedOriginPatterns("*")  // 允许所有源域,允许前端所有的服务器跨域访问.allowCredentials(true);  // 允许凭证请求,允许携带cookie}
}

3.3、SysUserServiceImpl

    @Overridepublic SysUser getUserInfo() {/*//从Redis中获取与token关联的json字符串String json = stringRedisTemplate.opsForValue().get(SpzxConst.LOGIN_USER_KEY_PREFIX + token);//如果json字符串为空,则抛出异常if (StringUtils.isEmpty(json)) {throw new SpzxException(ResultCodeEnum.LOGIN_STATUS_ERROR);}//解析json字符串为SysUser对象并返回*///SpzxLoginAuthInterceptor.SYS_USERS_MAP.get(token);//System.out.println(Thread.currentThread());//return SpzxLoginAuthInterceptor.SYS_USERS_MAP.get(Thread.currentThread());return SpzxLoginAuthInterceptor.THREAD_LOCAL.get();}

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

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

相关文章

【Oracle APEX开发小技巧1】转换类型实现显示小数点前的 0 以 及常见类型转换

在 apex 交互式式网格中&#xff0c;有一数值类型为 NUMBER&#xff0c;保留小数点后两位的项&#xff0c;在 展示时小数点前的 0 不显示。 效果如下&#xff1a; 转换前&#xff1a; m.WEIGHT_COEFFICIENT 解决方案&#xff1a; 将 NUMBER&#xff08;20&#xff0c;2&#xf…

Vue 自定义ElementUI的Loading效果

import { loadingText, messageDuration } from "/settings";import { Loading } from "element-ui"; // loadingText、messageDuration 这两个参数我是调的公共配置文件,按自己需求来 const install (Vue, opts {}) > {/* 全局多彩Loading加载层 *…

cpolar:通过脚本自动更新主机名称和端口号进行内网穿透【免费版】

cpolar 的免费版经常会重新分配 HostName 和 Port&#xff0c;总是手动修改太过麻烦&#xff0c;分享一下自动更新配置文件并进行内网穿透的方法。 文章目录 配置 ssh config编写脚本获取 csrf_token打开登陆界面SafariChrome 设置别名 假设你已经配置好了服务器端的 cpolar。 …

Spring AI 调用 openAI 进行语音识别

Spring AI支持语音识别功能&#xff0c;目前仅支持OpenAI的Transcription模型。 项目搭建&#xff1a; 参考 Spring AI 介绍以及与 Spring Boot 项目整合 源码示例&#xff1a; RestController RequestMapping("/openai") public class OpenAiIAudioTranscriptionC…

1964springboot VUE 智慧社区可视化平台系统开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot VUE社区可视化平台系统是一套完善的完整信息管理类型系统&#xff0c;结合springboot框架和VUE完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码…

Android Studio main,xml 视图代码转换

Android Studio main,xml 视图&&代码转换 其实很简单,但是对我们小白来说还是比较蒙的。 废话不多说,直接上图。 我的Android Studio 是 4.0 版的 我刚打开是这个界面,在我想学习如何用代码来布局,可能大家也会找不见代码的位置。 follow me 是不是感觉很简单呢。…

【usb设备端口异常】——使用ls /dev/video*查看设备号时出现报错:ls:无法访问‘/dev/video*‘: 没有那个文件或目录

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、ls:无法访问/dev/video*: 没有那个文件或目录1. 问题描述2. 原因分析3. 解决方法 总结 前言 一、ls:无法访问’/dev/video*: 没有那个文件或目录 使用的这…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 披萨大作战(100分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…

《梦醒蝶飞:释放Excel函数与公式的力量》4.1if函数

第4章&#xff1a;逻辑与条件函数 第一节4.1 if函数 在Excel中&#xff0c;逻辑函数用于处理基于特定条件的真假判断&#xff0c;它们是构建复杂公式和进行高级数据分析的基础。本章将深入探讨逻辑函数的使用方法&#xff0c;特别是IF函数&#xff0c;这是Excel中最为常用的条…

1 UC

1 UC 1、环境变量2、环境变量表3、错误处理4、库文件4.1 静态库4.2 动态库4.3 动态库的动态加载 5、虚拟地址 1、环境变量 什么是环境变量&#xff1f; 每个进程都有一张自己的环境变量表&#xff0c;表中的每个条目都是形如“键值”形式的环境变量。进程可以通过环境变量访问…

计算机毕业设计Python深度学习房价预测 房价可视化 链家爬虫 房源爬虫 房源可视化 卷积神经网络 大数据毕业设计 机器学习 人工智能 AI

基于python一/二手房数据爬虫分析预测系统可视化 商品房数据Flask框架&#xff08;附源码&#xff09; 项目介绍python语言、Flask框架、MySQL数据库、Echarts可视化 sklearn机器学习 多元线性回归预测模型、requests爬虫框架 链家一手房 一手房数据商品房数据、分析可视化预测…

前后端分离的后台管理系统源码,快速开发OA、CMS网站后台管理、毕业设计项目

那有没有一款软件解-决这种现状呢?答案是肯定的。引入我们的软件——eladmin。 介绍 ELADMIN,一个简单且易上手的 Spring boot 后台管理框架,已发布 Mybatis-Plus 版本,为开发者提供了一个全-面、高-效的解-决方案。 特点 高-效率:前后端完全分离,项目简单可配,内置代码…

在windows和linux服务器之间互传文件

最近需要在windows上和linux服务器上实现相互传送文件&#xff0c;作为一个linux小白&#xff0c;研究了一个上午&#xff0c;终于成功了&#xff0c;记录一下。 使用的是SFTP方式。 Linux服务器系统是 Ubuntu 18.04 64位&#xff0c;windows 是 win10专业版。 首先在Linux服…

http和https的区别在哪

HTTP&#xff08;超文本传输协议&#xff09;和HTTPS&#xff08;超文本传输安全协议&#xff09;之间存在几个关键区别主要涉及安全性、端口、成本、加密方式、搜索引擎优化&#xff08;SEO&#xff09;、身份验证等方面 1、安全性&#xff1a;HTTP&#xff08;超文本传输协议…

Web前端项目-页面动态背景【附完整源码】

页面动态背景 一&#xff1a;花瓣背景 页面效果&#xff1a; HTML代码 <!DOCTYPE HTML> <HTML> <TITLE>花瓣漫舞</TITLE> <META NAME"Generator" CONTENT"EditPlus"> <META NAME"Author" CONTENT"&quo…

区块链技术:探索7个物联网应用的潜力

在当今数字化时代&#xff0c;区块链技术逐渐成为一种受到广泛关注的技术创新。本文将以《区块链技术&#xff1a;探索7个物联网应用的潜力》为题&#xff0c;介绍区块链技术在物联网领域的七个应用潜力。物联网作为未来发展的重要方向&#xff0c;结合区块链技术的应用将为我们…

【因果推断python】47_元学习1

目录 S-Learner 简单回顾一下&#xff0c;我们现在感兴趣的是发现治疗效果的异质性&#xff0c;即确定单位对治疗的不同反应。在这个框架中&#xff0c;我们想估计 或 在连续的情况下。换句话说&#xff0c;我们想知道这些单位对治疗的敏感程度。这在我们不能治疗所有人并且需…

Flink 1.19.1 standalone 集群模式部署及配置

flink 1.19起 conf/flink-conf.yaml 更改为新的 conf/config.yaml standalone集群: dev001、dev002、dev003 config.yaml: jobmanager address 统一使用 dev001&#xff0c;bind-port 统一改成 0.0.0.0&#xff0c;taskmanager address 分别更改为dev所在host dev001 config.…

【SD3的Turbo也来了】Jasper AI用Flash Diffusion的蒸馏技术为SD3提速

Flash Diffusion 是一种新颖的图像生成方法&#xff0c;旨在显著提高现有条件扩散模型&#xff08;例如教师模型&#xff09;的速度&#xff0c;而无需牺牲性能。它通过引入以下技术来实现这一点&#xff1a; 蒸馏损失&#xff1a;在教师模型和学生模型之间引入蒸馏损失&#…

React+TS前台项目实战(十三)-- 全局常用响应式加载动画Loading组件封装

文章目录 前言Loading组件1. 功能分析2. 代码详细注释3. 使用方式4. 不同尺寸loading动画效果展示 总结 前言 高阶组件有几大优点&#xff0c;其中一个就是渲染劫持&#xff0c;如懒加载&#xff0c;是否显示该元素loading&#xff0c;这在项目中我们经常用到。毫无疑问&#…