1、背景

  年初,从外地转移阵地到西安,转眼已两个多月。很久不写业务代码了,到了新公司,条件恶劣到前所未有,从需求,设计,架构,实现,实施,测试,bug修复,项目计划制定,项目管理,全他妈我一个人,关键是平台很大,很多技术难点,时间还又紧,要命的是,公司销售左派盛行,连技术老大都是销售出身,直属领导设计出身不懂技术。。。点到为止,剩下的大家自行脑补。吐槽归吐槽,事儿还是得干,程序猿的基本素养不是。于是一个多月,996式搞法,项目上线了,其中包括那个我半天做出来的短信验证码。。。废话大半天,终于说到今天的重点了,那就言归正传。

  对于短信验证码,前阵子,看到骚窝洞见分享了一篇短信验证码的文章(https://insights.thoughtworks.cn/sms-authentication-login-api/),感觉可以作为一个最佳实践了,老早就决定按照文中观点实践了,奈何那阵一直996,没时间,直到最近,才忙里偷闲动手整理。原文不再赘述,这里就文中对于短信验证码的关键要点,截图如下:

2.实现

  首先,直接上解决方案截图:

  典型的应用层 =》 服务层调用架构,采用接口层及IOC解耦。我们先看工具库,Captcha.Util,重点说下ImageCaptchaHelper与MsgCaptchaHelper。图形验证码,这里要致敬EdiWang,图形验证码直接盗版的他的(https://edi.wang/post/2018/10/13/generate-captcha-code-aspnet-core)。整个文件中代码太长,就不贴了,这里只给几个要点:

(1)生成图形验证码的工程,需要标记unsafe,如下:

这是因为图形验证码的生成有部分用到了指针相关,熟悉C#的朋友应该对这个背景知识不陌生:

不用关心这是啥啥啥,照着设置unsafe就成了,我他妈压根儿就懒得看这段指针代码,就是看了也不一定看得懂。。。

(2)图形验证码的位置调整:    

  代码中,X,Y的值,就是验证码构成字符中,各个字符的二维偏移量,越大,偏移就可能越厉害。注释掉的是原来的,下边一行是我调整过后的,因为实际使用中发现不少情况下会出现字符超出边框界限,没法儿认的情况。

(3)噪音线处理

不管是偏移也好,噪音线也好,本质上都是为了降低OCR识别率。for循环的次数,代表噪音线条数,条数越多,可能就越难辨识。之所以从3到5条随机,改为固定2条,是因为实际使用时发现,当噪音线随机成5条时,很多图形验证码基本人眼没法儿辨识,没骗过机器,估计先把人眼晃瞎喽。

  以上就是图形验证码中需要注意或者自己需要调整的几个点。接下来,我们看短信验证码的生成:

  简单粗暴,传入短信验证码长度,是多少位,我就拼接多少个随机生成的数字字符构成满足长度要求的验证码。

  接下来,是Service层,图形验证码、短信验证码的核心逻辑都在这里,整个工程就一个服务CaptchaService。首先,我们看看服务层依赖:

  其中内存缓存的作用,是缓存图形验证码、短信验证码,供后续校验、过期使用,带会让详述。这里为了演示核心主题,使用了内存缓存,如果是大型生产环境,尤其是高并发的情况,可能需要分布式缓存,甚至还可能需要搭配消息队列。core寄宿环境接口,目的是为了开发环境或测试环境下,直接返回短信验证码的值而无需真实发送短信验证码,生产环境再调用第三方运行商发送短信验证码。

  接下来,我们看图形验证码的请求:

  可以看见,生成随机图形验证码之后,以图形验证码类型,手机号,外加ImgCaptcha前缀拼接,作为图形验证码的key缓存图形验证码的值。控制器层的处理如下:

  拿到短信验证码结果之后,以图形验证码二进制流为基础构建FileStreamResult返回。这里需要特别注意的是,MemoryStream不能按照最佳实践用using包围起来,因为了解MVC或webapi请求处理管道的应该知道,当前FileStreamResult返回后并不是立即处理,而是在管道的某个阶段及某个特定时候才处理控制器方法的返回结果,假如这里using包起来了,那控制器方法执行完毕,memorystream也就释放了,将来FileStreamResult执行时候就会直接异常。

 

  这里没啥好说的,就是按照同样的构造键取出图形验证码并与客户端发送过来的比对,相同就校验通过。

  接下来,看看短信验证码的请求:

  请求短信验证码,需要把对应的图形验证码一并随请求发过来。这里额外交代一下,图形验证码类型,短信验证码类型是需要一一对应的,实际业务中,我们可能有注册验证码,找回密码验证码,修改密码验证码,各种业务验证码等,每种业务验证码对应的图形验证码类型和短信验证码类型应该是对应的,如果为了减少错误,可以定义两个枚举,这里因为是想把验证码做成通用服务,所以类型并未根据具体业务定义枚举。回到发送短信验证码的实现上,可以看到,首先就校验图形验证码,图形验证码校验通过的情况下,按照与图形验证码Key类似的规则构建短信验证码缓存key,并从缓存找是否存在对应的短信验证码缓存对象。如果找到了,则说明相同手机号的相同业务已经获取过短信验证码且指定时间内未失效,这种情况下,是不能获取短信验证码的,否则视为短信轰炸,直接返回。示例中,或者说按照骚窝最佳实践要点中,一分钟之内是只能获取一条的, 所以我定了60s,并做时差提示。假如不存在对应短信验证码,则构造短信验证码对象,分别设置短信码、创阿金时间为当前时间、校验次数为0,并缓存。最后,根据当前是开发还是生产环境,决定是直接返验证码还是真实发送短信。

  最后,看短信验证码校验:

  逻辑蛮简单,首先按照指定键取短信验证码缓存,取到了,再看该缓存对象校验次数,如果超过3次了,则直接拦截,视为暴力攻击。未超过,则校验次数累加,并比对,相同则视为OK。这里需要特别注意的是,进程内缓存,设置完校验次数就OK了,可以不用回写缓存,但如果是分布式缓存,则需要回写修改过的短信验证码对象至缓存。至此,核心逻辑实现部分差不多了,接下来我们看实际效果。

3.运行效果:

  首先,请求图形验证码

  接下来,校验此图形验证码。我们先用正确的校验:

  再用错误的去校验:

  正确的校验成功,错误的校验失败,那么校验部分OK了。然后,我们看看,用此图形验证码去获取短信验证码,我们先用错误的图形验证码去校验:

  好,已经失败了,那我们换正确的试试:

   可以看到,短信验证码已经发送成功了。我们再发送一次:

  这时候,系统提示,获取太频繁了,请20s后再。因为我在码字,时间过去了点儿,所以是20s,这时间是根据当前时间减去短信验证码创建时间,在与60s的频率限制求差值,来算倒计时的。好,现在我们拿刚才的短信验证码去校验:

  。。。我日,码字的这会儿,短信验证码缓存过期了。。。算了,这次哥从图形验证码开始整连贯的截图吧,码字先放一边儿

(1)获取图形验证码:

(2)校验图形验证码:

(3)获取短息验证码:

(4)用正确短信验证码校验(第1次校验):

(5)用错误验证码校验(第2次):

(6)用错误验证码校验(第3次):

(7)用正确验证码校验(第4次):

  注意最后几张短信验证码校验的截图结果,前3次,正确的验证码校验成功,错误的校验失败,第4次开始,因为已经达到校验上线3次,所以直接失效了,不管验证码正确与否。

  好,废话的这会儿,应该又失效了,我们再重现下:

4.源码

  https://github.com/KINGGUOKUN/Captcha.git。整个解决方案是服务化的,可以开箱即用。

5.总结

  我们再回过头来看看骚窝的短信验证码核心要点:

  这么多要点中,本方案有两个没有实现,如截图所示,同一个手机号在同一时间内可以有多个有效的短信验证码以及第三方api,第三方api说的并不明确,到底是什么,而且如果是集成第三方了,那么可能就用不上短信验证码了,直接用户名、密码、第三方api就直接了,至于另一条,同一手机号同一时间内可以有多个有效的短信验证码,个人感觉不太实用和必要。假如要实践的话,其实也简单,方案中短信验证码模型中,并不是保存单个短信验证码,而是缓存验证码列表就OK了,这点不难。

  以上便是个人结合骚窝的最佳实践要点,个人实践了一道。早就想搞的,奈何最近一直996,无法言说吧。希望能对各位有用。

原文地址:https://www.cnblogs.com/guokun/p/11042903.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 

短信验证码“最佳实践”相关推荐

  1. Java实现短信验证码最佳实践

    1.背景 2.实现 3.运行效果: 4.源码 5.总结 1.背景 年初,从外地转移阵地到西安,转眼已两个多月.很久不写业务代码了,到了新公司,条件恶劣到前所未有,从需求,设计,架构,实现,实施,测试, ...

  2. go 服务接入短信验证码功能(对接阿里云平台)

    简介 短信验证码还是比较常用的功能,已经有了很成熟的方案,本篇介绍的是对接阿里云的短信服务,一条短信大概两分钱. 基本的流程是: 到对应的云平台申请权限,大致费用都差不多 照着官方文档进行对接,并集成 ...

  3. python实现第三方验证码获取_python利用第三方模块,发送短信验证码(测试案例)...

    今天学到个利用python第三方,发送短信验证码的代码,速实现一遍,短信立即收到,果断记录在案! 环境:虚拟机上centos7平台,python2.7版本: 第三方服务提供商是:云通讯官网:www.y ...

  4. Java实现短信验证码(阿里云短信服务)

    前言: 很多时候我们做的项目都需要上图这样的验证码来帮助我们完成更好的功能,比如:什么登录注册,忘记密码需要发送手机验证码之类的啊...下面分享我今天通过阿里云短信服务实现的短信验证码,操作都很简单, ...

  5. [小黄书后台]手机短信验证码

    上一章我们实现了将图片上传到又拍云上的功能.今天我们会实现手机验证码的功能. 我们现在到处都会碰到手机验证码的验证方式,比如在注册的时候,通过输入手机号码,获取一个验证码,然后输入完成注册. 1. 螺 ...

  6. 【免费的短信推送API】【MobTech】【Android】手机短信验证码推送

    前言 作业需要用到:短信验证码推送(用于注册).了解到一个免费的手机短信推送平台,就去官网看了看相关API怎么用. http://www.mob.com/wiki/detailed?wiki=SMSS ...

  7. 短信验证码—Java实现

    在业务需求中我们经常会用到短信验证码,比如手机号登录.绑定手机号.忘记密码.敏感操作等,都可以通过短信验证码来保证操作的安全性,于是就记录下了一次开发的过程. 一.架构设计 发送短信是一个比较慢的过程 ...

  8. 注意这两点,就可以提升企业短信验证码的发送速度

    短信验证码是企业的刚需,不管是用户注册还是用户通知,作用总是不可代替.快速的短信验证码,可以明显提升用户体验,也可以给用户留下一个好印象.下面给大家介绍一下提升短信验证码速度方法. 第一.服务器相应速 ...

  9. android 短信验证码的实现

    公司用的短信验证码是Mob.com 网址:http://www.mob.com 进入网站 注册登录之后 进入后在上面有应用是让选择android还是ios 之类的,点击下载SDK --选择免费短信验证 ...

最新文章

  1. Python入门学习之函数
  2. java工资高还是php_java和php哪个工资高
  3. 计算机课题推荐人意见,课题推荐人意见怎么写
  4. Leetcode题解(22)
  5. 大数据平台助力核与辐射安全监管
  6. 前端开发大师修炼指南
  7. kafka数据 落盘_终于知道Kafka为什么这么快了!
  8. wpf mysql课程设计_使用 WPF 和 MySQL 搭建小型人资管理系统——主要页面
  9. 独木难成林,不管是自己在支付宝单种还是钉钉合种,都是在做公益
  10. Ubuntu触摸屏校准命令
  11. 二项分布与伯努利试验的关系,看图说话
  12. 全国计算机类大学排名二本,二本计算机大学排名,二本计算机大学排名
  13. 机器自动翻译古文拼音 - 十大宋词 - 扬州慢 淮左名都 姜夔
  14. GPIO之推挽输出和开漏输出
  15. TCP/IP协议卷一(一)
  16. 推荐系统论文笔记(1):Hybrid Recommender Systems:Survey and Experiments
  17. Disruptor无锁ringbuff实现
  18. 河北北方学院计算机二级考试安排,2021年河北北方学院开学时间入学考试及新生转专业相关流程说明...
  19. Qt for Python关于新6.3版本的详细信息
  20. 2J53磁滞电动机转子永磁和金

热门文章

  1. oracle服务器不识别tc服务,记一次ORACLE无法启动登陆事故
  2. 如何做Teams Bot的测试覆盖
  3. google天气预报接口_将天气预报添加到谷歌浏览器
  4. vue使用process.env搭建自定义运行环境
  5. cocos android-1,cocos2dx在windows下开发,编译到android上(1)
  6. 新手AS常见问题集锦
  7. 基于css3的鼠标滑动按钮动画之CSS--续
  8. js遮罩层以及移动端的上拉框
  9. 用ADO.NET的ExecuteScalar方法返回单一值-资讯动态
  10. Unix操作系统***追踪反击战