短信登录功能如何实现?

简介:

在日常生活中我们登录/注册某些网站/APP是通常可以选择 密码登录和手机号登录

为什么手机号发送后会有验证码返回呢?

网站如何识别我的验证码是否正确?

如果我的个人网站也想要实现短信登录功能,具体该如何实现?

下面我将从用户的视角带着大家一步一步的了解短信登录背后的一切细节。

在这里插入图片描述

在这里插入图片描述

具体操作

输入手机号
在这里插入图片描述

点击【获取验证码
在这里插入图片描述
后台:

验证手机号

//Slfg4    日志注解
    public Result sendCode(String phone, HttpSession session) {
        //1:先验证手机号格式  不符合就返回错误信息
        if(RegexUtils.isPhoneInvalid(phone)){
            //2:如果不符合,返回错误信息
            return Result.fail("手机号格式错误");
        }
            //4:生成验证码
            String code = RandomUtil.randomNumbers(6);
           //保存验证码到redis phone作为key 并且有一个公共前缀

            stringRedisTemplate.opsForValue()
            .set(RedisConstants.LOGIN_CODE_KEY +phone,code
                    ,RedisConstants.CACHE_NULL_TTL,TimeUnit.MINUTES);
            //6:发送验证码  此处是返回到前端
            log.debug("验证码是{}",code);
            return Result.ok();
    }
  • 符合格式 生成验证码 将其存在redis中并发送给前端

输入验证码

点击【注册并登录

  • 后台以手机号为key与redis中存储的验证码进行比对 不相同则返回 “验证码不正确”
  • 相同则看是否被注册过 并生成token
  • 如果没有注册则新建用户数据并插入新数据
  • 将用户的信息和token存入redis的map中
@Override
  public Result login(LoginFormDTO loginForm, HttpSession session) {
      //获取手机号
      String phone = loginForm.getPhone();
      if(RegexUtils.isPhoneInvalid(phone)){
          //2:如果不符合,返回错误信息
          return Result.fail("手机号格式错误");
      }
      //从reids中拿出验证码
      String code = stringRedisTemplate.opsForValue()
      .get(RedisConstants.LOGIN_CODE_KEY + phone);
      if(loginForm.getPhone().equals(code)){
          //如果验证码错误直接返回false
          return Result.fail("验证码不正确");
      }
      //如果正确 在确定手机号是否已经被注册过
      User user = query().eq("phone", phone).one();
      //生成token  用hutool工具类生成的uuid toString(true)可以把uuid中的-去掉
      String token = UUID.randomUUID().toString(true);
      if(user==null){
          //没有注册过新建并插入新数据
          user=CreateNewUser(phone);
      }
      //hutool工具类 Beanutil
      UserDTO userDTO= BeanUtil.copyProperties(user, UserDTO.class);
      //运用redis中的map数据结构存储userDto对象
      Map<String,String> map=new  HashMap<>();
      map.put("id",userDTO.getId().toString());
      map.put("nickName",userDTO.getNickName());
      map.put("icon",userDTO.getIcon());
      stringRedisTemplate.opsForHash()
      .putAll(RedisConstants.LOGIN_USER_KEY+token,map);
      //设置时间一般是30分钟不进行操作,就会失效
      stringRedisTemplate
      .expire(RedisConstants.LOGIN_USER_KEY+token, 
      RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);
    return Result.ok(token);
  }
  
  private User CreateNewUser(String phone) {
   User user=new User();
   user.setPhone(phone);
   user.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(4));
   save(user);
   return  user;
  }

验证成功 开始登录 拦截器的实现

  • 拦截器 一:更新token信息/放行空token 用token从redis里拿出map对象转化为UserDTO对象存入ThreadLocal中,通过所有拦截器后释放
  • 拦截器二:判断ThreadLocal中有没有UserDTO对线,有则放行,没有拦截

在这里插入图片描述

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值