Redis实现session共享(基于手机短信验证码)

1.点击发送验证码

1.1校验手机格式 如果错误则返回

1.2生成6位随机数验证码

1.3把验证码保存到redis并设置过期时间 以手机号码作为key 短信号码作为value

1.4发送到控制台

public Result sendCode(String phone, HttpSession session) {
        //1,校验手机号
        if(RegexUtils.isPhoneInvalid(phone)){
            //2,如果不符合,返回错误信息
            return  Result.fail("手机号格式错误");
        }
        //3,符合,生成验证码
        String code = RandomUtil.randomNumbers(6);
        //4.保存验证码到redis  有效期两分钟 set key value ex 120
        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY+phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);
        //5,发送验证码
        log.debug("发送短信验证码成功,验证码:"+code);
        //返回ok
        return Result.ok();
    }

2.登录

2.1校验手机号

2.2从redis获取验证码并校验

2.3如果一致,查询数据库如果不存在就创建然后保存

2.4随机生成token

2.5把user转化为map

2.6把userMap信息存入redis(以token为key) hashset

2.7设置token(key)有效时期

2.8把token返回给浏览器

public Result login(LoginFormDTO loginForm, HttpSession session) {
        String phone = loginForm.getPhone();
        //1,校验手机号
        if(RegexUtils.isPhoneInvalid(phone)){
            //2,如果不符合,返回错误信息
            return  Result.fail("手机号格式错误");
        }
        //3,从redis获取验证码并校验
        String sessionCode =stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY+phone);
        String code = loginForm.getCode();
        if(sessionCode==null||!sessionCode.equals(code)){
            //3,不一致,报错
            return Result.fail("验证码错误");
        }
        //4,一致,根据手机号查询用户  select *from tb_user where phone =?
        User user = query().eq("phone", phone).one();
        //5,判断用户是否存在
        if(user==null){
            //6,不存在 创建用户并保存
            user=creteUserWithPhone(phone);
        }
        //TODO 7,存在,保存用户到redis中
        //TODO 7.1 随机生成token
        String token = UUID.randomUUID().toString();
        //TODO 7.2 将User对象转为hash储存
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        Map<String, Object> map = BeanUtil.beanToMap(userDTO, new HashMap<>(),
                CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));
        //TODO 7.3 储存user到redis
        String tokenKey=LOGIN_USER_KEY+token;
        stringRedisTemplate.opsForHash().putAll(tokenKey,map);
        //设置token有效期
        stringRedisTemplate.expire(tokenKey,LOGIN_USER_TTL,TimeUnit.MINUTES);
​
        //TODO 7.4返还token
        return Result.ok(token);
    }

3.token刷新机制 通过拦截器

3.1通过request拿到token

3.2如果token为空直接返回 进入二层拦截器

3.3通过token拿到redis中的用户。判断用户是否存在 若不存在直接返回进入二层拦截器

3.4把用户转为userDTO对象

3.5保存在ThreadLocal之中

3.6刷新token有效期

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //TODO 1获取请求头中token
        String token = request.getHeader("authorization");
        if (StrUtil.isBlank(token)){//如果token为空
           return true;
        }
        //TODO 2 基于token获取redis 中的用户
        Map<Object, Object> entries = stringRedisTemplate.opsForHash()
                .entries(RedisConstants.LOGIN_USER_KEY + token);
        //TODO 3 判断用户是否存在
        if(entries.isEmpty()){
            return true;
        }
        //TODO 5 将查询到的Hash数据转为UserDto对象
        UserDTO userDTO = BeanUtil.fillBeanWithMap(entries, new UserDTO(), false);
        //TODO 6 存在保存信息到ThreadLocal
        UserHolder.saveUser(userDTO);
        // TODO 7.刷新token有效期
        stringRedisTemplate.
                expire(RedisConstants.LOGIN_USER_KEY + token,RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);
        return true;
    }

4.二层拦截器

4.1.从ThreadLocal里面拿user如果为null直接返回flase拦截

4.2如果不为null 就返回ture 通行

//二层拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      //判断是否需要拦截
        if(UserHolder.getUser()==null){
            response.setStatus(401);
            return false;
        }
        //有用户就放行
        return true;
    }
     @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //移除用户
        UserHolder.removeUser();
    }

UserHolder代码

public class UserHolder {
    private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>();
​
    public static void saveUser(UserDTO userId){
        tl.set(userId);
    }
​
    public static UserDTO getUser(){
        return tl.get();
    }
​
    public static void removeUser(){
        tl.remove();
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值