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

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 {

    @Resource
    StringRedisTemplate stringRedisTemplate;

    /**
     * 生成圆形验证码的图片和验证码字符串,并将其存储在Redis中以供后续验证使用。
     * 验证码图片以Base64编码的形式返回,同时返回验证码在Redis中的键值。
     *
     * @return 包含验证码键和Base64编码的验证码图片的映射。
     */
    @Override
    public 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 如果登录参数错误、用户名不存在、验证码错误或密码错误,则抛出异常
     */
    @Override
    public 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进制数字组成  按照时间递增 的唯一id
        String 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 deleted
        from sys_user
        where 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 {

    @Resource
    private 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<>();

    @Override
    public 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;
    }

    @Override
    public 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 {

    @Resource
    private SpzxLoginAuthInterceptor spzxLoginAuthInterceptor;

    @Resource
    private SpzxLoginAuthProperties spzxLoginAuthProperties;

    @Override
    public 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

    @Override
    public 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();
    }
  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值