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、参考、在线调试

网址:https://api.aliyun.com/new#/?product=Dysmsapi&api=SendSms&params=%7B%22RegionId%22%3A%22cn-hangzhou%22%2C%22PhoneNumbers%22%3A%22%22%2C%22SignName%22%3A%22%22%2C%22TemplateCode%22%3A%22%22%7D&tab=DEMO&lang=JAVA

Aps.Net Core3.1 WebApi发送阿里云短信验证码的更多相关文章

  1. php 阿里云短信验证码

    阿里云短信服务:https://dysms.console.aliyun.com 1.准备 1.1.创建签名.模板 1.2.创建.使用阿里云秘钥 地址:https://usercenter.conso ...

  2. c#阿里云短信验证码

    发送验证码 private static void SendAcs(string mobile, string templateCode, dynamic json, int ourid) { if ...

  3. .netcore 使用阿里云短信

    准备工作 阿里云上申请短信服务 创建短信应用.签名.短信模板并申请审核,如果审核不通过,接口是调不通的. 配置专门用来发短信的accessKeyId和 accessKeySecret 开始开发 下载安 ...

  4. php与阿里云短信接口接入

    使用阿里云短信API,需要在控制台获取以下必要参数,其中需要自己手机验证+官方审核多次,尤其审核需要保持耐心. 1. accessKeyId  相当于你的个人账户密钥: 2. accessKeySec ...

  5. 阿里云短信服务验证码封装类 - PHP

    本文记录在ThinkPHP6.0中使用阿里云短信验证码,该封装类不仅仅局限于TP,拿来即用 使用该类之前必须引入 flc/dysms 扩展,该封装类就是基于这个扩展写的 composer requir ...

  6. 使用Node.js调用阿里云短信的发送以及接收

    为了使用Node.js调用阿里云短信服务,我自己写了个npm包, 目前实现了: 使用Node.js调用阿里云短信服务,发送短信: 使用Node.js调用阿里云短信服务以及MNS服务,接收用户上行短信 ...

  7. php 阿里云短信服务及阿里大鱼实现短信验证码的发送

    一:使用阿里云的短信服务 ① 申请短信签名 ②申请短信模板 ③创建Access Key,获取AccessKeyId 与 AccessKeySecret.(为了安全起见,这里建议使用子用户的Access ...

  8. Abp 添加阿里云短信发送

    ABP中有短信发送接口ISmsSender public interface ISmsSender { Task<string> SendAsync(string number, stri ...

  9. flask+阿里云短信服务实现注册发送手机验证码

    效果图: 该效果主要讲解实现通过调用阿里云的SDK实现发送注册验证码短信(阿里云短信付费使用) 购买阿里云短信服务 购买链接:https://www.aliyun.com/product/sms 1. ...

随机推荐

  1. JMeter实战(一) 体系结构

    此为开篇,介绍JMeter的组成结构,阅读后对JMeter形成整体认知和初步印象. 为了便于后续讲解,先明确下2个术语. 元件:如HTTP请求.事务控制器.响应断言,就是一个元件. 组件:如逻辑控制器 ...

  2. Linux系统常用API总结

    1.错误处理 - fprintf() - perror() 2.通用I/O模型 - fd = open(pathname, flags, mode) - numread = read(fd, buff ...

  3. (SpringBoot-Jpa)使用Idea数据库自动脚本Generate POJOS生成 Entity对象,

    因:使用SpringBoot -jpa,需要手动配置Entity 但是如果你的表中有很多属性,或者有很多表怎么办?? 每个手动写? 还是用mybatis.写mapper??? 解决:使用idea自动工 ...

  4. 多测师讲解selenium_运行报告相出错归纳_高级讲师肖sir

    <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'> EETraceback (most recent c ...

  5. 第4天 | 12天搞定Python,基础语法(下)

    为了方便你的学习,减轻负重,我特意将基础语法分成上下两部分.希望你喜欢这种方式,如果不喜欢,你可以跟我说,反正我是不会改的,哈哈~~. 如果上部分,你还没看的话,先去看<第4天 | 12天搞定P ...

  6. RLP序列化算法

    RLP RLP(Recursive Length Prefix)递归长度前缀编码,是由以太坊提出的序列化/反序列化标准,相比json格式体积更小,相比protobuf对多语言的支持更强. RLP将数据 ...

  7. Jetson AGX Xavier部署ORB_SLAM2(ROS)

    1. 修改CMakeLists.txt Examples/ROS/ORB_SLAM2下的CMakeLists.txt 原 set(LIBS ${OpenCV_LIBS} ${EIGEN3_LIBS} ...

  8. 【图论】USACO07NOV Cow Relays G

    题目大意 洛谷链接 给定一张\(T\)条边的无向连通图,求从\(S\)到\(E\)经过\(N\)条边的最短路长度. 输入格式 第一行四个正整数\(N,T,S,E\),意义如题面所示. 接下来\(T\) ...

  9. Ubuntu安装zookeeper问题

    在Ubuntu系统安装zookeeper后,启动报错: root@host8:/usr/solrcould/service1/zookeeper-3.5.0-alpha# sh bin/zkServe ...

  10. 视频和音频的 DOM

    视频和音频的 DOM HTML5 DOM 为 <audio> 和 <video> 元素提供了方法.属性和事件. HTML5 Audio/Video 方法 方法 描述 addTe ...