文章目录
- 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拦截器创建&注册
springmvc拦截器 登录验证&放行首页请求
springmvc拦截器 预检请求放行
springmvc拦截器 使用CurrentHashMap透传登录状态
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();}