手机验证码登录 思路及实战

前言

随着手机号码实名制以来,手机验证码登录已经算是大趋势了,其优点一是不用伤脑筋去记什么账号,直接输入自己手机号码就行了,省事;其二是便捷,只需要通过手机接收的短信验证码即可完成登录,整个流程给用户体验非常好,很流畅;其三是处理事件时更迅速,比如账号出现异常情况,可以第一时间通过短信方式提示用户该如何应对。还有好多利于用户的地方,这里不一一举例了,进入主题,撸代码~

梳理流程

接入短信SDK这里不做说明,默认已经接入成功,可调用发送短信

和大部分手机验证码登录一样,大体流程如下:

  • 用户输入手机号码,点击获取验证码,调用后台获取验证码接口,后端接收用户手机号,生成验证码并返回

  • 用户接收到验证码后点击登录,调用手机验证码登录接口,后台接收用户手机号和验证码,根据校验结果返回对应数据或状态

正文

第一步,后端接收用户输入的手机号码,生成验证码,发送短信验证码至用户手机

说明:

  1. 为了做到灵活配置性,通过参数seconds支持前端定义验证码有效时长,如果前端未设置则取默认值1分钟

  2. 通过手机号生成缓存key,存储短信验证码并设置生效时间,便于后续用户发起登录时做校验

代码如下:

    /**
     * 发送登录验证码
     * @param mobile    手机号
     * @param seconds   有效时长(单位: 秒)
     * @return          验证码
     */
    public R sendCaptcha(String mobile, Integer seconds){
        Redis redis= RedisManager.getRedis();
        String key = BaseConstant.PHONE_LOGIN_KEY + mobile;
        //默认有效时长60秒
        Integer effTime = 60;
        if (redis.exists(key)){
            return R.error("验证码仍在有效期");
        }
        if(StringUtils.isEmpty(mobile)){
            return R.error("参数mobile不能为空");
        }
        if(seconds != null){
            effTime = seconds;
        }
        String captcha = "";
​
        try{
            //查询短信余额
            Integer smsNum = (Integer) (queryBal().get("data"));
            if(smsNum == 0){
                return R.error("短信余额不足,请联系平台续费!");
            }
​
            StringBuffer sb = new StringBuffer();
            //生成六位随机数
            captcha = String.valueOf((int)((Math.random() * 9 + 1 ) * 100000));
            String content = "您的登录验证码为: " + captcha + ",有效时长" + effTime/60 + "分钟,请尽快完成登录,如非本人操作请忽略此短信!";
            sb.append("username=" + SmsConstant.SMS_USERNAME)
                    .append("&userpwd=" + SmsConstant.SMS_PASSWORD)
                    .append("&mobiles=" + mobile)
                    .append("&content=" + URLEncoder.encode(SmsConstant.SMS_SIGN + content, "UTF-8"));
​
            //发送请求
            String resultXml = HttpUtil.sendPost(SmsConstant.SEND_URL, sb.toString());
            AdminSms adminSms = new AdminSms();
            adminSms.setMobile(mobile);
            adminSms.setContent(content);
            adminSms = parseXml(resultXml, adminSms);
            if(adminSms.getErrorcode() == 1){
                //存储redis缓存----根据前端传递的有效时长缓存验证码
                redis.setex(key, effTime-1, captcha);
                //存储短信数据
                adminSms.setSendTime(new Date());
                adminSms.save();
            }
        } catch (Exception e) {
            Log.getLog(getClass()).error("发送短信验证码异常: ", e);
        }
​
        return R.ok().put("data", captcha);
    }

 

第二步,用户接收到验证码后点击登录,调用手机验证码登录接口,后台接收用户手机号和验证码,根据校验结果返回对应数据或状态

说明:

  1. 通过上一步我们利用手机号码生成的缓存key,捞取验证码,做对应的校验处理,失败则返回提示信息,成功则返回登录凭证及所需的用户数据即可

  2. 通过缓存中设置的验证码生效时长,控制验证码的可使用时间

代码如下:

/**
     * 用户登录----手机验证码登录
     * @author Ivan
     * @param mobile    手机号
     * @param captcha   验证码
     */
    public void phoneLogin(@Para("mobile") String mobile, @Para("captcha") String captcha){
        AdminUser user = AdminUser.dao.findFirst(Db.getSql("admin.user.queryByMobile"), mobile.trim());
        if (user == null) {
            renderJson(R.error("该手机号码未注册!"));
            return;
        }
        if (user.getStatus() == 0) {
            renderJson(R.error("账户被禁用!"));
            return;
        }
        Redis redis= RedisManager.getRedis();
        String key = BaseConstant.PHONE_LOGIN_KEY + mobile;
        if (redis.exists(key)) {
            String redisRusult = redis.get(key);
            if(!redisRusult.equals(captcha)){
                renderJson(R.error("验证码输入错误!"));
                return;
            }
        } else {
            renderJson(R.error("验证码已失效!"));
            return;
        }
        if (user.getStatus() == 2) {
            user.setStatus(1);
        }
        //获取用户名缓存
        String usernameKey = BaseConstant.USER_LOGIN_ERROR_KEY + user.getUsername();
        redis.del(usernameKey);
        String token = IdUtil.simpleUUID();
        user.setLastLoginIp(ServletUtil.getClientIP(getRequest()));
        user.setLastLoginTime(new Date());
        user.update();
        user.setRoles(adminRoleService.queryRoleIdsByUserId(user.getUserId()));
        redis.setex(token, 3600, user);
        Integer type = getParaToInt("type", 1);
        BaseUtil.setToken(user.getUserId(), token, type);
        renderJson(R.ok().put("Admin-Token", token).put("user", user).put("auth", adminRoleService.auth(user.getUserId())));
    }

 

结语

通过以上两步(两个接口),已经完成了整个手机验证码登录流程,由于目前的项目用的是Jfinal框架,此处代码也以Jfinal为例,其他框架实际上也是大同小异,主要看的是设计思路。

 

标题:手机验证码登录 思路及实战

地址:http://blog.ivan.group/article/21

文章转载自:Ivan | 晏飞个人博客 [http://blog.ivan.group]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值