Skip to content
DAILY QUOTE

“ ”

  • 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;
}