从用户输入手机验证码开始

image

验证用户的有效性或者安全性,是每一个系统必备的安全措施,在移动端优先的时代,利用手机验证码来验证用户,算是安全系数比较高的手段。放眼当下几乎全部的互联网应用几乎都开放了手机验证码登陆,并且应用内的敏感操做都须要手机验证码或者指纹,甚至面部识别来肯定当前操做人的权限。算法

抛开其余端,单就移动端App方式而言,若是用户频繁进行敏感操做,须要频繁发送验证码,其实在用户体验上并不友好,何况短信费用也随之增长。就App形式而言,验证一个用户的有效性其实能够演变为验证设备的有效性,即:当前人在当前设备上是否可信。设计模式

image

如下讨论只针对非Web(浏览器)环境,Web环境其实也能够根据浏览器的信息来生成一个相似设备标示的代码

不少系统在设计之初,就已经考虑到安全主设备的概念,就像微信,若是在同一个手机上打开是不须要每次都进行登陆操做的。进行设备验证是每一个安全系统比较重要的部分,推荐在系统设计之初就要考虑。回归正题,对于不少行业来讲,用户在App内频繁进行一些敏感操做是很正常的,好比我所在的在线教育行业,老师会很频繁的在一个班级内添加学生和老师(咱们认为这些操做属于敏感操做)。若是每次都须要老师发送验证码来进行操做,那交互上真的是太不友好。要想保证业务操做的安全性以及改善交互操做,咱们就须要抽象出问题的根本所在。浏览器

发送验证码操做最终的目的是为了验证操做人是操做人,听起来很绕是否是。实现这个最终目的,其实有不少解决方案,其中用户可信设备就属于其中一类,而手机验证码方式又是用户可信设备实现的一种方式,具体来讲有几点:安全

  1. 用户利用手机验证码在这个设备上进行过敏感操做,就认为这个设备在一段时间内是可信任的。
  2. 用户在可信任的设备上进行其余敏感操做,若是在有效期内,就能够作到不发送验证码
  3. 用户的敏感操做也能够进行分级,最高敏感级必须输入验证码才能够进行操做(好比重置密码,验证码登录),通常敏感级在可信设备有效期内能够不输入验证码。

image

基于以上所说,系统设计的时候就能够抽象出一个用户可信设备中心,包括敏感操做的定义,可信设备的有效时长,可信设备的定义(好比:验证码经过的设备可定义为有效设备)等等概念。经过这样设计,短信验证只不过成为验证用户信任设备的一种途经,彻底能够作到和具体业务无关(敏感级别最高操做除外),通常敏感的操做业务接口也能够避免添加验证码参数,真正的把验证和业务相分离,岂不美哉?微信

通过这样抽象,用户可信设备中心其实本质的接口只有几个:数据结构

  1. 验证设备是否有效
  2. 设置设备有效
  3. 设备有效的途经(例如短信验证码方式)

固然你的系统首先要有设备的概念,若是非要写几行代码的话架构

  1. 验证设备有效
public async Task<int> CheckUserDevice(UserDeviceReq para)
        {
            
            if (para == null || string.IsNullOrWhiteSpace(para.DeviceName) || para.UserId <= 0)
            {
                return 0;
            }
            //检查签名
            var sign = EncrypHelper.MD5Encrypt($"{SysConfig.SecretKey}_{para.UserId}_{para.DeviceName}");
            if (sign != para.Sign)
            {
                return 0;
            }
            string key = $"{para.UserId}_{para.DeviceName}";
            var authRet = await RedisClient.GetString(key);
            if (string.IsNullOrWhiteSpace(authRet))
            {
                //告诉客户端须要短信验证码
                return 414000;
            }
            return 1;
        }
  1. 设置设备有效
public async Task<int> SetUserDevice(UserDeviceReq para)
        {
            
            if (para == null || string.IsNullOrWhiteSpace(para.DeviceName) || para.UserId <= 0)
            {
                return 0;
            }
            //检查签名
            var sign = EncrypHelper.MD5Encrypt($"{SysConfig.SecretKey}_{para.UserId}_{para.DeviceName}");
            if (sign != para.Sign)
            {
                return 0;
            }
            string key = $"{para.UserId}_{para.DeviceName}";
            var cacheRet = await RedisClient.GetString(key);
            if (string.IsNullOrWhiteSpace(cacheRet))
            {
                UserDeviceInfo value = new UserDeviceInfo() { UserId = para.UserId, DeviceName = para.DeviceName, OperationCode = para.OperationCode, CreateDate = DateTime.Now, Context = "" };
                var userDeviceExp = SysConfig.GetAppSetting("Config:UserDeviceExpire");
                if (string.IsNullOrWhiteSpace(userDeviceExp))
                {
                    userDeviceExp = "300";
                }
                var authRet = await RedisClient.SetString(key, JsonConvert.SerializeObject(value), TimeSpan.FromMinutes(int.Parse(userDeviceExp)));
                if (!authRet)
                {
                    return 0;
                }
            }
            return 1;
        }

更多精彩文章并发

image

相关文章
相关标签/搜索