短信验证这样的功能是不是进本每个应用都会用到?那么你有积累下相关的开发模块或服务了吗?不管有没有,今天TJ给大家推荐一个现成的短信验证功能的开源项目!

一个合规、安全、可靠的短信验证码项目模块应该具备以下几点特征:

  • 发送的验证码存在一定时间的有效期

  • 验证码不宜过长或过短

  • 同一手机号码不能频繁发送验证码请求

  • 验证码被使用后就失效

这个Captcha项目,恰巧都符合这些特征。

让小编欣慰的是,代码里的注释都是中文,减低了不少学习难度,我们先看下这个短信验证项目一切的基础,生成验证码

using System;
using System.Collections.Generic;
using System.Text;namespace Captcha.Util
{/// <summary>/// 短信验证码工具类/// </summary>public static class MsgCaptchaHelper{/// <summary>/// 生成指定位数的随机数字码/// </summary>/// <param name="length"></param>/// <returns></returns>public static string CreateRandomNumber(int length){Random random = new Random();StringBuilder sbMsgCode = new StringBuilder();for (int i = 0; i < length; i++){sbMsgCode.Append(random.Next(0, 9));}return sbMsgCode.ToString();}}
}

十分清晰,就是运用随机函数生成满足长度要求的验证码,这里面长度是根据参数传入的,小编认为一般合理的验证码长度是6位,太短了容易被攻破,太长了的话使用起来对用户太不友好。看来6真是一个神奇的数字~

接着就是主要逻辑实现的service层

using Captcha.Dto;
using Captcha.Service.Contract;
using Captcha.Util;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Text;namespace Captcha.Service
{public class CaptchaService : ICaptchaService{#region Private Fieldsprivate readonly IMemoryCache _cache;private readonly IHostingEnvironment _hostingEnvironment;#endregion#region Constructorspublic CaptchaService(IMemoryCache cache, IHostingEnvironment hostingEnvironment){_cache = cache;_hostingEnvironment = hostingEnvironment;}#endregion#region Public Methods/// <summary>/// 获取图片验证码/// </summary>/// <param name="imgCaptchaDto">图形验证码请求信息</param>/// <returns></returns>public CaptchaResult GetImageCaptcha(ImgCaptchaDto imgCaptchaDto){var captchaCode = ImageCaptchaHelper.GenerateCaptchaCode();var result = ImageCaptchaHelper.GenerateCaptcha(100, 36, captchaCode);_cache.Set($"ImgCaptcha{imgCaptchaDto.ImgCaptchaType}{imgCaptchaDto.Mobile}", result.CaptchaCode);return result;}/// <summary>/// 验证图片验证码/// </summary>/// <param name="imgCaptchaDto">图形验证码信息</param>/// <returns></returns>public bool ValidateImageCaptcha(ImgCaptchaDto imgCaptchaDto){var cachedImageCaptcha = _cache.Get<string>($"ImgCaptcha{imgCaptchaDto.ImgCaptchaType}{imgCaptchaDto.Mobile}");if (string.Equals(imgCaptchaDto.ImgCaptcha, cachedImageCaptcha, StringComparison.OrdinalIgnoreCase)){return true;}else{return false;}}/// <summary>/// 获取短信验证码/// </summary>/// <param name="msgCaptchaDto">短信验证码请求信息</param>/// <returns></returns>public (bool, string) GetMsgCaptcha(MsgCaptchaDto msgCaptchaDto){if (string.IsNullOrWhiteSpace(msgCaptchaDto.ImgCaptcha)){throw new BusinessException((int)ErrorCode.BadRequest, "请输入图形验证码");}var cachedImageCaptcha = _cache.Get<string>($"ImgCaptcha{msgCaptchaDto.MsgCaptchaType}{msgCaptchaDto.Mobile}");if (!string.Equals(msgCaptchaDto.ImgCaptcha, cachedImageCaptcha, StringComparison.OrdinalIgnoreCase)){return (false, "验证失败,请输入正确手机号及获取到的图形验证码");}string key = $"MsgCaptcha{msgCaptchaDto.MsgCaptchaType}{msgCaptchaDto.Mobile}";var cachedMsgCaptcha = _cache.Get<MsgCaptchaDto>(key);if (cachedMsgCaptcha != null){var offsetSecionds = (DateTime.Now - cachedMsgCaptcha.CreateTime).Seconds;if (offsetSecionds < 60){return (false, $"短信验证码获取太频繁,请{60 - offsetSecionds}秒之后再获取");}}var msgCaptcha = MsgCaptchaHelper.CreateRandomNumber(6);msgCaptchaDto.MsgCaptcha = msgCaptcha;msgCaptchaDto.CreateTime = DateTime.Now;msgCaptchaDto.ValidateCount = 0;_cache.Set(key, msgCaptchaDto, TimeSpan.FromMinutes(2));if (_hostingEnvironment.IsProduction()){//TODO:调用第三方SDK实际发送短信return (true, "发送成功");}else        //非生产环境,直接将验证码返给前端,便于调查跟踪{return (true, $"发送成功,短信验证码为:{msgCaptcha}");}}/// <summary>/// 验证短信验证码/// </summary>/// <param name="msgCaptchaDto">短信验证码信息</param>/// <returns></returns>public (bool, string) ValidateMsgCaptcha(MsgCaptchaDto msgCaptchaDto){var key = $"MsgCaptcha{msgCaptchaDto.MsgCaptchaType}{msgCaptchaDto.Mobile}";var cachedMsgCaptcha = _cache.Get<MsgCaptchaDto>(key);if (cachedMsgCaptcha == null){return (false, "短信验证码无效,请重新获取");}if (cachedMsgCaptcha.ValidateCount >= 3){_cache.Remove(key);return (false, "短信验证码已失效,请重新获取");}cachedMsgCaptcha.ValidateCount++;if (!string.Equals(cachedMsgCaptcha.MsgCaptcha, msgCaptchaDto.MsgCaptcha, StringComparison.OrdinalIgnoreCase)){return (false, "短信验证码错误");}else{return (true, "验证通过");}}#endregion}
}

这里不得不夸一句,项目比小编想的更周到,除了小编之前想到的那些功能,还加入了发送验证码之前需要完成图形校验的功能,也就是我们常见的拖拉图案到正确的位置这一动作。

这里运用到ImageCaptchaHelper.GenerateCaptchaCode();这个方法,据说是一个现成的图形校验生成方法,是一个名叫Edi Wang的大神开源提供的。

实话说,小编看了半天其中具体的实现逻辑,唔,没怎么看明白。。。因为里面用到了一些.net指针的方法,小编实在是。。。那说好听点嘛就是术业有专攻,但小编知道这种时候,我们就先用起来就行了!这里主要运用就是将生成图形验证码和手机号码绑定,从而达到在短信验证码请求信息中,进行正确的手机和对应图形验证码的校验:

if (string.IsNullOrWhiteSpace(msgCaptchaDto.ImgCaptcha)){throw new BusinessException((int)ErrorCode.BadRequest, "请输入图形验证码");}var cachedImageCaptcha = _cache.Get<string>($"ImgCaptcha{msgCaptchaDto.MsgCaptchaType}{msgCaptchaDto.Mobile}");if (!string.Equals(msgCaptchaDto.ImgCaptcha, cachedImageCaptcha, StringComparison.OrdinalIgnoreCase)){return (false, "验证失败,请输入正确手机号及获取到的图形验证码");}

同时,service还实现了小编想的同一手机号码不能频繁发送验证码请求效果,并且这个时间也是通过参数来控制。

return (false, $"短信验证码获取太频繁,请{60 - offsetSecionds}秒之后再获取");

在验证阶段,程序完成了对缓存中验证码是否存在的校验,是否使用过的校验,像这个例子里面,是将使用次数设定为3次,如果超过3次的才会被认定无效,如果想严谨点的,可以直接设为1次。

if (cachedMsgCaptcha == null){return (false, "短信验证码无效,请重新获取");}if (cachedMsgCaptcha.ValidateCount >= 3){_cache.Remove(key);return (false, "短信验证码已失效,请重新获取");}cachedMsgCaptcha.ValidateCount++;if (!string.Equals(cachedMsgCaptcha.MsgCaptcha, msgCaptchaDto.MsgCaptcha, StringComparison.OrdinalIgnoreCase)){return (false, "短信验证码错误");}else{return (true, "验证通过");}

整体的运行逻辑,其实都在service层完成了。小伙伴想额外增加其他校验的话也可以在这段逻辑里面自行增加,总的来说呢,这个项目逻辑清晰,即插即用,扩展性也不错,也非常适合想学习的小伙伴明白一个短信验证码从生成、发送、校验、生效通过这样一个完整的链路。

随着互联网的发展,光靠简单的密码密钥很难确保安全,短信验证想必会越来越普及,想学习了解的小伙伴,乘着假期赶紧来学习一波吧~项目完整地址如下:

点击下方卡片,关注公众号“TJ君

回复“短信验证”,获取仓库地址

收下这个“短信验证”的最佳实践项目!相关推荐

  1. java实现阿里云短信验证注册--详细教程

    java实现阿里云短信验证注册–详细教程 .项目中先引入依赖 <!--阿里云短信包--><dependency><groupId>com.aliyun</gr ...

  2. Springboot实现短信验证登录

    一.介绍 使用短信验证登录也是现在实际项目中普遍使用的一种登录, 二.实际的操作流程 1.用户在前端页面输入手机号码之后,点击发送验证码 2.前端将手机号传给后端 3.后端生成一个6为的随机数通过短信 ...

  3. 解决mob网站短信验证SDK更新后,android studio下的mob短信验证接入问题

    对于android开发来说,遇到需要短信注册验证的问题是很常见的,今天我们就来聊一聊在android studio上SMSSDK的接入.废话不多说:具体步骤如下: (1)打开我们的mob官网:http ...

  4. GitHub 二次验证收不到短信咋办?

    身在天朝,用了国外的代码托管服务,会有些烦恼的. 网速慢就不说了,如果启用了二次验证,短信收不到那就悲催了. 之前的都能收到短信的,突然间尝试了很多天都不行,联系github的客服,几次的答复如下: ...

  5. SpringBoot下实现华为云短信验证功能(含代码)

    准备工作 登入华为云控制台,找到"消息&短信"模块,找到国内短信(本次开发只针对国内用户),下面分别有 应用管理–签名管理–模板管理 三块 自上而下依次添加应用,首先是 应 ...

  6. 简单的短信验证功能的实现

    相信有很多朋友在做三方登陆的时候会加入短信验证的功能,最近刚好被分配安排实现这一需求,本人新手一枚,特地去网上搜了资料,目前用的比较多的大汉.云通讯还有MOB的smssdk,对比之下,最终选择了完全免 ...

  7. 手机老是收不到短信验证码?我来告诉你为什么!

    有些用户在使用某产品时可能会出现短信验证码收不到的情况,同事之前也遇到过这样的情况,连续发送多次依然收不到短信.那么短信验证码为什么会发送失败.原因有哪些呢.#短信验证码安全 现在短信验证码服务在各种 ...

  8. 银行卡怎么突然收不到短信信息服务器,银行卡开通了短信通知功能为什么没收到通知?十条原因看清楚...

    朋友说,自己的银行卡已经在银行设置了短信通知功能,为什么资金变动没有收到通知呢?会有风险吗? 大家知道,短信通知功能在银行是收费功能,大多数银行每个月3元左右,目的就是及时了解账户金额的变动,以防范风 ...

  9. 注册app短信验证平台_APP短信对接选择怎样的平台

    很多APP为了安全都会使用到短信验证,比如说我们在某些APP上注册的时候,就需要输入手机号,然后输入收到的短信内容才能继续操作.这个过程其实就是APP短信对接后的效果.试想下如果我们很长时间收不到短信 ...

最新文章

  1. MySQL重置root用户密码的方法
  2. 提高开发效率之安卓模板(上面有四种模板的教程,我之前会两种,看完之后还是只会两种2333)
  3. 前端开发--播放页面评论区业务逻辑初步
  4. confluence安装_Hive安装
  5. 【贪心】畜栏预定(ybtoj 贪心-1-3)
  6. java版本号管理_微服务项目中如何管理依赖版本号?
  7. 【转】测试工程师日常工作需要关注的问题
  8. 用notepad++打造自己的C/C++语言IDE --是时候和DOS屏幕说再见了
  9. 【服务器】【个人图床】宝塔安装Chevereto
  10. NE555脉冲模块电路
  11. [Pku 2777] 线段树(六) {总结}
  12. 基于RV1126平台imx291分析 --- 总结
  13. “看来少宇这家伙身上有着惊天的秘密啊
  14. Chrome 中的自动播放策略如何设置自动播放
  15. 用python画一条虚线_Python3 tkinter基础 Canvas create_line 画实线与虚线
  16. 供应链安全 | 北京大学软件工程国家工程研究中心 张世琨:软件供应链安全的风险和成因分析
  17. 自动驾驶仿真软件SCANeR studio(三)terrain地形模式
  18. 婴儿脸上起湿疹吃什么好
  19. 计算机在教育领域中的应用方式,计算机技术在教育中的应用
  20. 蓝桥杯javac组我们的征途是星辰大海

热门文章

  1. 继续- 管理百人研发团队的烦恼(下)
  2. web渗透测试 靶机系统 漏洞测试环境
  3. TCP keepAlive详解(TCP心跳包)
  4. 窗体的扩展样式GWL_EXSTYLE: 用于SetWindowLong
  5. Linux C编程--进程间通信(IPC)3--信号集和发送信号介绍
  6. Python学习之While--break
  7. 模块加载过程代码分析1
  8. Linux下逻辑地址-线性地址-物理地址图解
  9. java浮点数化为整数_如何在JavaScript中将浮点数转换为整数?
  10. thinkphp5 mysql uuid_TP6_基类控制器如何向中间件传参