Aps.Net Core3.1 WebApi发送阿里云短信验证码
1、前言
转眼又要过了一年了 好久没写博客了,人不学就要落后,今天有时间把以前弄的发送阿里云短信验证码登录记录一下。
2、准备条件
1)去阿里云官网注册一个账号。有账号直接登录就行,以前新人好像有免费的短信可以学习 ,现在我们只能购买了 先开通短信服务然后去购买 购买链接
2)跳转到控制台的短信服务点击国内消息签名模板 右边点添加签名。后面在模板管理哪里添加模板 。
模板这个签名的意思就是 发送短信验证码的头部,类似于发票的抬头文字 一般个人只能申请一个验证码签名。企业的不知道(没试过。。。)。模板就是具体的内容,里面可以使登录的验证码 注册的验证码 找回密码的验证码 加上签名就是 【xxx时光管】 您好,你登录的验证码是520886。【】不用写在签名里面 发短信的时候会自动加上。个人的签名不能包含一些企业的文字 到时候他会告诉你签名、模板注意事项。
3)查看个人的accessKeyId跟accessSecret 右上角点个人头像点击AccessKey管理。没有的就创建一个,有的话就看列表点击查看Secret 然后验证一下就可以了,记住这两个key
3、Core 代码
1)写一个发送验证码的辅助类SMS
- public class SMS
- {
- /// <summary>
- /// 发送短信
- /// </summary>
- /// <param name="phone">手机号码</param>
- /// <param name="code">验证码</param>
- /// <param name="templateName">验证码模板</param>
- /// <param name="accessKeyId">accessKeyId= LTAIA8bLXzkMsKR4JB8</param>
- /// <param name="secret">secret= SamAiMzbdC0yS1lo6u9O9r</param>
- /// <param name="signName">签名名称</param>
- /// <returns></returns>
- public static SendMessageDto SendSMS(string phone, string code, string templateName, string accessKeyId, string secret, string signName)
- {
- var ret = new SendMessageDto();
- IClientProfile profile = DefaultProfile.GetProfile("cn-hangzhou", accessKeyId, secret);
- DefaultAcsClient client = new DefaultAcsClient(profile);
- CommonRequest request = new CommonRequest
- {
- Method = MethodType.POST,
- Domain = "dysmsapi.aliyuncs.com",
- Version = "2017-05-25",
- Action = "SendSms"
- };
- request.AddQueryParameters("PhoneNumbers", phone);
- request.AddQueryParameters("SignName", signName);
- request.AddQueryParameters("TemplateCode", templateName);
- request.AddQueryParameters("TemplateParam", $"{{'code':'{code}'}}");
- // request.Protocol = ProtocolType.HTTP;
- try
- {
- CommonResponse response = client.GetCommonResponse(request);
- var result = Encoding.Default.GetString(response.HttpResponse.Content);
- var resultJson = JsonConvert.DeserializeObject<SendMessageDto>(result);
- ret = resultJson;
- }
- catch (ServerException e)
- {
- Console.WriteLine(e);
- }
- catch (ClientException e)
- {
- Console.WriteLine(e);
- }
- return ret;
- }
- }
- public class SendMessageDto
- {
- /// <summary>
- /// 状态码的描述。
- /// </summary>
- public string Message { get; set; }
- /// <summary>
- /// 请求ID。
- /// </summary>
- public string RequestId { get; set; }
- /// <summary>
- /// 发送回执ID,可根据该ID在接口QuerySendDetails中查询具体的发送状态。
- /// </summary>
- public string BizId { get; set; }
- /// <summary>
- /// 请求状态码。 返回OK代表请求成功。
- /// </summary>
- public string Code { get; set; }
- }
2)验证码配置类SMSConfig
- /// <summary>
- /// 验证码配置类
- /// </summary>
- public class SMSConfig
- {
- public string AccessKeyId { get; set; }
- public string AccessSecret { get; set; }
- public string SignName { get; set; }
- public Login Login { get; set; }
- public Regist Regist { get; set; }
- public Reset Reset { get; set; }
- }
- /// <summary>
- /// 验证码模板
- /// </summary>
- public class Login
- {
- /// <summary>
- /// 类型 1登录 2注册 3找回、重置密码
- /// </summary>
- //public int Type { get; set; }
- /// <summary>
- /// 模板名称
- /// </summary>
- public string TemplateName { get; set; }
- }
- public class Regist
- {
- /// <summary>
- /// 模板名称
- /// </summary>
- public string TemplateName { get; set; }
- }
- public class Reset
- {
- /// <summary>
- /// 模板名称
- /// </summary>
- public string TemplateName { get; set; }
- }
3)数据库建立一张表存储验证码
- public partial class SysSendSms
- {
- /// <summary>
- /// Id
- /// </summary>
- [Key]
- [Column("Id", Order = 0)]
- [Required()]
- [Display(Name = "Id")]
- public int Id { get; set; }
- /// <summary>
- /// 验证码
- /// </summary>
- [Column("Code")]
- [StringLength(20, ErrorMessage = "{0}长度不能超过20个字符")]
- [Display(Name = "验证码")]
- public string Code { get; set; }
- /// <summary>
- /// 手机号
- /// </summary>
- [Column("Phone")]
- [StringLength(20, ErrorMessage = "{0}长度不能超过20个字符")]
- [Display(Name = "手机号")]
- public string Phone { get; set; }
- /// <summary>
- /// 发送时间
- /// </summary>
- [Column("SendTime")]
- [Display(Name = "发送时间")]
- [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd HH:mm:ss:ffff}")]
- public DateTime? SendTime { get; set; } = DateTime.Now;
- /// <summary>
- /// gid
- /// </summary>
- [Column("Guid")]
- [StringLength(36, ErrorMessage = "{0}长度不能超过36个字符")]
- [Display(Name = "Guid")]
- public string Guid { get; set; }
- /// <summary>
- /// 次数
- /// </summary>
- [Column("Count")]
- [Display(Name = "次数")]
- public int? Count { get; set; }
- /// <summary>
- /// 是否用了
- /// </summary>
- [Column("IsUsed")]
- [Display(Name = "领取数量")]
- public bool? IsUsed { get; set; }
- /// <summary>
- /// 类型1登陆 2注册
- /// </summary>
- [Column("Type")]
- [Display(Name = "类型1登陆 2注册")]
- public int? Type { get; set; }
- }
这个type可以自己定义,我这边演示一个登陆的发送验证码
4)发送短信方法
- public async Task<Result> SendSMSAsync(SendSmsDto sendSmsDto)
- {
- var code = new Random().Next(1000, 9999).ToString();
- var templateName = sendSmsDto.Type switch
- {
- 1 => _smsConfig.Value.Login.TemplateName,
- 2 => _smsConfig.Value.Regist.TemplateName,
- _ => _smsConfig.Value.Login.TemplateName
- };
- return await Send(sendSmsDto.Phone, sendSmsDto.Type, code, templateName);
- }
- /// <summary>
- /// 发送短信验证码
- /// </summary>
- /// <param name="phone">手机</param>
- /// <param name="type">类型(后面数据库好区分,防止乱发)</param>
- /// <param name="code">验证码</param>
- /// <param name="templateName">模板申请下来对应的Code</param>
- /// <returns></returns>
- private async Task<Result> Send(string phone, int type, string code, string templateName)
- {
- //手机号相同 密码相同 没有用过的
- var model = _db.SysSendSms.OrderByDescending(x=>x.SendTime).FirstOrDefault(x => x.Phone == phone && x.Type == type && x.IsUsed == false);
- var guid = Guid.NewGuid().ToString("N");
- var dt = DateTime.Now;//时间
- if (type == 1)//登录
- {
- var ckuser = _db.Customer.Any(x => x.Phone == phone);
- if(!ckuser)
- {
- var cus = new Customer
- {
- Phone = phone,
- LoginID = phone,
- Gid = Guid.NewGuid().ToString("N"),
- Pwd = SecurityHelper.MD5(phone)
- };
- _db.Customer.Add(cus);
- _db.SaveChanges();
- return await CkSend(phone, type, code, templateName, model, guid, dt);
- }
- else
- return await CkSend(phone, type, code, templateName, model, guid, dt);
- }
- else
- return Result.ToFail("请求参数错误,type");
- }
检查发送验证码的方法 为了防止恶意乱发
- /// <summary>
- /// 看看以前发过没有
- /// </summary>
- /// <param name="phone"></param>
- /// <param name="type"></param>
- /// <param name="code"></param>
- /// <param name="templateName"></param>
- /// <param name="model"></param>
- /// <param name="guid"></param>
- /// <param name="dt"></param>
- /// <returns></returns>
- private async Task<Result> CkSend(string phone, int type, string code, string templateName, SysSendSms model, string guid, DateTime dt)
- {
- if (model == null)//没有发送过
- {
- var sendMess = SMS.SendSMS(phone, code, templateName, _smsConfig.Value.AccessKeyId, _smsConfig.Value.AccessSecret, _smsConfig.Value.SignName);
- if (sendMess.Code == "OK")
- {
- await SaveData(phone, type, code, guid, dt);
- return Result.ToSuccess(new { code });
- }
- else
- return Result.ToFail("短信验证码发送失败" + sendMess.Code + sendMess.Message);
- }
- else
- {
- var co = model.Count;//发送次数
- if (co >= 5 && dt.AddHours(-5) < model.SendTime)//大于3次并且时间在3个小时内
- return Result.ToFail("短信验证码发送频繁,请3个小时再试");
- else /*(co >= 8 && dt.AddDays(-1) < model.SendTime)//大于8次并且时间在24个小时内*/
- {
- var sendMess = SMS.SendSMS(phone, code, templateName, _smsConfig.Value.AccessKeyId, _smsConfig.Value.AccessSecret, _smsConfig.Value.SignName);
- if (sendMess.Code == "OK")
- {
- model.Count++;
- model.SendTime = DateTime.Now;
- model.Code = code;
- _db.SaveChanges();
- return Result.ToSuccess(new { code });
- }
- else
- return Result.ToFail("短信验证码发送失败"+ sendMess.Code+sendMess.Message);
- }
- }
- }
- /// <summary>
- /// 保存发送信息到数据库
- /// </summary>
- /// <param name="phone"></param>
- /// <param name="type"></param>
- /// <param name="code"></param>
- /// <param name="guid"></param>
- /// <param name="dt"></param>
- /// <returns></returns>
- private async Task SaveData(string phone, int type, string code, string guid, DateTime dt)
- {
- var modelSMS = new SysSendSms
- {
- Code = code,
- Phone = phone,
- SendTime = dt,
- Guid = guid,
- Count = 1,
- IsUsed = false,
- Type = type
- };
- _db.SysSendSms.Add(modelSMS);
- await _db.SaveChangesAsync();
- }
我这边的逻辑其实是写死的 type只能是1 就是这个用户不在数据库里面先创建用户 然后发送验证码。在里面就直接发送验证码。下面是登录方法
- public async Task<Result> LoginAsync(LoginDto loginDto)
- {
- try
- {
- var model = _db.Customer.FirstOrDefault(x => x.LoginID == loginDto.Phone);
- if (model != null)
- {
- var send = _db.SysSendSms.OrderByDescending(x => x.SendTime).FirstOrDefault(x => x.Code == loginDto.Code);
- if (send == null)
- return Result.ToFail("手机验证码错误");
- else
- {
- Dictionary<string, string> keyValues = new Dictionary<string, string>()
- {
- {"Id",model.LoginID }
- };
- var token = _tokenHelper.CreateToken(keyValues);
- send.IsUsed = true;
- model.Token = token.TokenStr;
- await _db.SaveChangesAsync();
- return Result.ToSuccess(token);
- }
- }
- else
- return Result.ToFail("用户不存在");
- }
- catch (Exception ex)
- {
- return Result.ToError(ex);
- }
- }
- public class LoginDto
- {
- /// <summary>
- /// 手机号码
- /// </summary>
- public string Phone { get; set; }
- /// <summary>
- /// 验证码
- /// </summary>
- public string Code { get; set; }
- }
如果验证成功了就要把数据库发送短信验证码的字段IsUse改成true
我的模板 签名都写在配置文件里面
- //短信验证码配置 所有配置来自阿里云官方
- "SMSConfig": {
- "AccessKeyId": "LTAI4GB1mA8bLXzkMsKR4JB8",
- "AccessSecret": "SamAiMzbZ4ufoNRndC0yS1lo6u9O9r",
- "SignName": "真猴吃", //签名名称
- "Login": {
- "TemplateName": "SMS_200700770" //登录模板代码
- },
- "Regist": {
- "TemplateName": "SMS_180347559" //注册模板代码
- },
- "Reset": {
- "TemplateName": "SMS_192835767" //找回密码模板代码
- }
- },
这与上面的接收类一样的格式 当然在Core里面别忘了配置连接字符串 再调用的类或者接口在startup里面注册
- services.Configure<SMSConfig>(Configuration.GetSection("SMSConfig"));
4、参考、在线调试
Aps.Net Core3.1 WebApi发送阿里云短信验证码的更多相关文章
- php 阿里云短信验证码
阿里云短信服务:https://dysms.console.aliyun.com 1.准备 1.1.创建签名.模板 1.2.创建.使用阿里云秘钥 地址:https://usercenter.conso ...
- c#阿里云短信验证码
发送验证码 private static void SendAcs(string mobile, string templateCode, dynamic json, int ourid) { if ...
- .netcore 使用阿里云短信
准备工作 阿里云上申请短信服务 创建短信应用.签名.短信模板并申请审核,如果审核不通过,接口是调不通的. 配置专门用来发短信的accessKeyId和 accessKeySecret 开始开发 下载安 ...
- php与阿里云短信接口接入
使用阿里云短信API,需要在控制台获取以下必要参数,其中需要自己手机验证+官方审核多次,尤其审核需要保持耐心. 1. accessKeyId 相当于你的个人账户密钥: 2. accessKeySec ...
- 阿里云短信服务验证码封装类 - PHP
本文记录在ThinkPHP6.0中使用阿里云短信验证码,该封装类不仅仅局限于TP,拿来即用 使用该类之前必须引入 flc/dysms 扩展,该封装类就是基于这个扩展写的 composer requir ...
- 使用Node.js调用阿里云短信的发送以及接收
为了使用Node.js调用阿里云短信服务,我自己写了个npm包, 目前实现了: 使用Node.js调用阿里云短信服务,发送短信: 使用Node.js调用阿里云短信服务以及MNS服务,接收用户上行短信 ...
- php 阿里云短信服务及阿里大鱼实现短信验证码的发送
一:使用阿里云的短信服务 ① 申请短信签名 ②申请短信模板 ③创建Access Key,获取AccessKeyId 与 AccessKeySecret.(为了安全起见,这里建议使用子用户的Access ...
- Abp 添加阿里云短信发送
ABP中有短信发送接口ISmsSender public interface ISmsSender { Task<string> SendAsync(string number, stri ...
- flask+阿里云短信服务实现注册发送手机验证码
效果图: 该效果主要讲解实现通过调用阿里云的SDK实现发送注册验证码短信(阿里云短信付费使用) 购买阿里云短信服务 购买链接:https://www.aliyun.com/product/sms 1. ...
随机推荐
- 一键安装PyCharm
1.准备阶段,首先去官网下载:https://download.jetbrains.8686c.com/python/pycharm-professional-2019.1.exe 官网地址:http ...
- 用于ASP.net的MVC模块
下载MVCBricks_SRC - 492.58 KB 表的内容 介绍系统要求游戏闪屏的最终考虑历史 介绍 自从我写上一篇关于ASP的文章以来,已经有很长时间了.净的话题.这次我决定写一些关于它的东西 ...
- React踩坑笔记 —— React
Webpack提供了自己的导入方式require.include,但同时也支持commonjs规范或AMD规范的require语法,而Node.js使用的就是common.js,ES6的语法Impor ...
- TP5调用小程序微信支付,回调,在待支付中再次调用微信支付
1,必须要有 $mch_id $key $appid这三个值,是需要去申请的,我是直接用公司的2,购买商品订单号用户openid统一下单名称商品价格(必须以分为单位,调起微信支付)服务器的ip地址(没 ...
- javascript里面的this指向问题
1:一般情况下this最终指向调用它的那个对象. 2:全局作用域或者普通函数中的this都会指向window. 例1:console.log(this); // 在控制台输出的是BOM顶级对象 wi ...
- spring-boot-route(十八)spring-boot-adtuator监控应用
Spring Boot提供了良好的服务监控模块,只需要通过简单的配置便可以完成服务监控和管理.但是服务监控这块内容往往是最容易被忽略的一块内容,今天我们一起来学习一下使用spring-boot-act ...
- 一口气看完45个寄存器,CPU核心技术大揭秘
序言 前段时间,我连续写了十来篇CPU底层系列技术故事文章,有不少读者私信我让我写一下CPU的寄存器. 寄存器这个太多太复杂,不适合写故事,拖了很久,总算是写完了,这篇文章就来详细聊聊x86/x64架 ...
- tomcat 登录主页成功 点击Manager App 401 等问题
1.将项目部署在tomcat的安装路径webapps下(如果报404,查下该应用是否在tomcat的webapps下部署着) 2.启动tomcat成功,http://127.0.0.1:8080成功, ...
- ubuntu 16.04 Chrome
打开终端 输入 命令1:sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/apt/sources.list ...
- 【应用服务 App Service】 App Service Rewrite 实例 - 反向代理转发功能
问题描述 在使用Azure App Service(应用服务)时,有时候需要在不同的站点之间进行跳转,但是希望通过通过访问同一个域名的方式来实现反向代理.如果创建应用时候选择的是Window服务,这时 ...