从用户输入手机验证码开始,验证用户的合法性或安全性,是每个系统必备的安全措施。在移动端优先的时代,使用手机验证码来验证用户被认为是具有比较高的安全系数。方法。纵观当今几乎所有的互联网应用,几乎所有的手机验证码登录都是可用的,应用中的敏感操作需要手机验证码或者指纹,甚至是面部识别来判断当前运营商的权限。抛开其他终端不谈,就移动端App而言,如果用户频繁进行敏感操作,需要频繁发送验证码,在用户体验上其实并不友好,短信费用也会相应增加.就App表单而言,验证用户的合法性实际上可以演变成验证设备的合法性,即:当前人在当前设备上是否可信。以下讨论仅针对非Web(浏览器)环境。事实上,Web环境也可以根据浏览器的信息生成类似于设备标签的代码。很多系统在设计之初就考虑到了安全主控设备的概念,就像微信一样,如果在同一个手机上打开,就不需要每次都登录。设备验证是每个安全系统的重要组成部分,建议在系统设计之初就考虑到。回到正题,对于很多行业来说,用户在APP中频繁进行一些敏感操作是很正常的。比如在我的在线教育行业,老师会经常给一个班级添加学生和老师(我们认为这些操作是敏感操作)。如果老师每次操作都需要发验证码,那交互真的太不友好了。为了保证业务运行的安全和提高互操作性,我们需要抽象出问题的根源。发送验证码操作的最终目的是验证运营商是否为运营商。听起来很混乱,不是吗?要实现这个最终目标,其实有很多解决方案,其中用户信任设备属于一类,手机验证码方式就是实现用户信任设备的一种方式。具体有几点:用户使用手机验证如果代码对本设备进行过敏感操作,则认为本设备在一段时间内是可信任的。如果用户在有效期内对可信设备进行了其他敏感操作,也可以对用户未发送验证码的敏感操作进行分级。最高敏感度必须输入验证码才能进行操作(如重置密码、验证码登录),一般敏感度在受信设备有效期内不需要输入验证码。基于以上,在设计系统时,可以抽象出一个用户可信设备中心,包括敏感操作的定义、可信设备的有效期、可信设备的定义(例如:通过验证码的设备可以被定义为有效设备)等。通过这种设计,短信验证只是验证用户对设备信任度的一种方式,可以完全与具体业务无关(灵敏度最高的操作除外)。一般敏感操作业务接口也可以避免添加验证码参数。真正把验证和业务分开不是很好吗?经过这样的抽象,用户可信设备中心其实只有几个必不可少的接口:验证设备是否有效,设置设备的有效方式(比如短信验证码方式)当然你的系统首先要有这个概念设备的,如果你必须写验证设备是有效的几行代码publicasyncTaskCheckUserDevice(UserDeviceReqpara){|para.UserId<=0){返回0;}//校验签名varsign=EncryptHelper.MD5Encrypt($"{SysConfig.SecretKey}_{para.UserId}_{para.DeviceName}");if(sign!=para.Sign){返回0;}stringkey=$"{para.UserId}_{para.DeviceName}";varauthRet=awaitRedisClient.GetString(key);if(string.IsNullOrWhiteSpace(authRet)){//告诉客户端需要短信验证码return414000;}返回1;}设置设备有效publicasyncTaskSetUserDevice(UserDeviceReqpara){if(para==null||string.IsNullOrWhiteSpace(para.DeviceName)||para.UserId<=0){返回0;}//检查签名varsign=EncrypHelper.MD5Encrypt($"{SysConfig.SecretKey}_{para.UserId}_{para.DeviceName}");if(sign!=para.Sign){返回0;}stringkey=$"{para.UserId}_{para.DeviceName}";varcacheRet=awaitRedisClient.GetString(key);if(string.IsNullOrWhiteSpace(cacheRet)){UserDeviceInfovalue=newUserDeviceInfo(){UserId=para.UserId,DeviceName=para.DeviceName,OperationCode=para.OperationCode,CreateDate=DateTime.Now,Context=""};varuserDeviceExp=SysConfig.GetAppSetting("Config:UserDeviceExpire");如果(字符串。IsNullOrWhiteSpace(userDeviceExp)){userDeviceExp="300";}varauthRet=awaitRedisClient.SetString(key,JsonConvert.SerializeObject(value),TimeSpan.FromMinutes(int.Parse(userDeviceExp)));如果(!authRet){返回0;}}返回1;更多精彩文章分布式并发系列架构设计系列趣味学习算法与数据结构系列设计模式系列