- UserServiceImpl
java
/**
* 发送短信验证码。
*
* 作用:
* 1.检验手机号格式是否正确;
* 2.格式不对,返回错误信息;
* 3.格式正确,生成验证码;
* 4.保存验证码到Redis;
* 5.模拟发送短信验证码;
*
* @param phone手机号
* @param session当前Session对象
* @return处理结果
*/
public Result sendCode(String phone, HttpSession session) {
//检验手机号格式是否正确
if(!RegexUtils.isPhoneInvalid(phone)) {
//格式不对,返回错误信息
return Result.fail("手机格式错误");
}
//格式正确,生成验证码
String code= RandomUtil.randomNumbers(6);
//保存验证码到Redis //set key value ex 120
stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY+phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);
//模拟发送短信验证码
log.debug("向{}发送短信验证码成功,验证码:{}",phone,code);
//返回ok
return Result.ok();
}
/**
* 校验验证码并完成登录。
*
* 作用:
* 1.检验手机号是否一致,不同请求,保持一致;
* 2.从Redis中获取验证码并校验;
* 3.如果没有发送验证码,或者验证码不一致;
* 4.不一致,返回错误;
* 5.一致,根据手机号查询用户;
*
* @param loginFormDTO登录表单DTO
* @param session当前Session对象
* @return处理结果
*/
public Result login(LoginFormDTO loginFormDTO, HttpSession session) {
//检验手机号是否一致,不同请求,保持一致
String phone=loginFormDTO.getPhone();
if(!RegexUtils.isPhoneInvalid(phone)) {
return Result.fail("手机号格式错误");
}
//从Redis中获取验证码并校验
String cacheCode=stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY+phone);
String code=loginFormDTO.getCode();
//如果没有发送验证码,或者验证码不一致
if(cacheCode==null||!cacheCode.toString().equals(code)) {
//不一致,返回错误
return Result.fail("验证码错误");
}
//一致,根据手机号查询用户
User user=query().eq("phone",phone).one();
//如果用户不存在,创建用户
if(user==null){
user=createUserWithPhone(phone);
}
//随机生成token,作为登录令牌
String token= UUID.randomUUID().toString(true);
//将User对象转为HashMap存储
UserDTO userDTO=BeanUtil.copyProperties(user,UserDTO.class);
Map<String,Object> userMap=BeanUtil.beanToMap(userDTO,new HashMap<>(),
CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((filedName,fieldValue)->fieldValue.toString()));
//保存用户信息到Redis中
String tokenKey=LOGIN_USER_KEY +token;
stringRedisTemplate.opsForHash().putAll(tokenKey,userMap);
//设置token有效期
stringRedisTemplate.expire(tokenKey,LOGIN_USER_TTL,TimeUnit.MINUTES);
//返回token
return Result.ok(token);
}- LoginInterceptor
java
/**
* 执行preHandle相关业务逻辑。
*
* 作用:
* 1.获取请求头中的token;
* 2.基于token获取Redis中的用户;
* 3.判断用户是否在存在;
* 4.不存在,拦截,响应状态码401:未授权;
* 5.将查询到的hash数据转换为UserDTO对象;
*
* @param request request参数
* @param response response参数
* @param handler handler参数
* @return处理结果
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取请求头中的token
String token=request.getHeader("authorization");
if(StrUtil.isBlank(token)){
response.setStatus(401);
return false;
}
//基于token获取Redis中的用户
String key=RedisConstants.LOGIN_USER_KEY+token;
Map<Object,Object> userMap=stringRedisTemplate.opsForHash().entries(key);
//判断用户是否在存在
if(userMap.isEmpty()){
//不存在,拦截,响应状态码401:未授权
response.setStatus(401);
return false;
}
//将查询到的hash数据转换为UserDTO对象
UserDTO userDTO=BeanUtil.fillBeanWithMap(userMap,new UserDTO(),false);
//存在,保存用户信息到ThreadLocal
UserHolder.saveUser(userDTO);
//刷新token有效期
stringRedisTemplate.expire(key,RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);
//放行
return true;
}