Go基于阿里云短信服务实现登录注册
阿里云短信服务: “如果您的应用或网站未上线,您可以通过控制台的发送测试功能,体验短信发送服务。详情请参见发送测试短信。”
现在很多软件或者网站在注册或者登录的时候可以选择手机号+验证码
登录或者注册,我就在想?我可不可以也实现这个功能。
但是因为我的应用没有上线,所以目前只能实现测试功能。
一、阿里云操作
这部分虽说有阿里云帮助文档,但毕竟第一次使用,磕磕绊绊摸索了好久。
- 首先进入阿里云网站,登录过后搜索短信服务
- 点击
产品详细页
,可以免费领取100条免费短信 ,打开产品文档
,可以更好的帮助我们学习和使用短信服务; - 点击
短信控制台
根据指引完成“申请资质
、申请签名
、申请模板
”。
- 点击AccessKey(我点击的是继续使用AccessKey),创建AccessKey,保存好AccessKey ID和AccessKey Sercet。(其他人可以通过AccessKey调用你的短信服务发短信,相当于短信服务的账号密码)
- 等待资质、签名、模板都审批通过后,选择好签名、模板,点击
调用API发送短信
- 输入参数,服务地址任选,当出现调用成功,状态码200时,就可以复制或下载SDK示例代码
- SDK版本任选,推荐V2.0。复制或者下载代码到本地。
二、在Go上的操作
(一)GO SDK
理论上这部分只要把AccessKeyId和AccessKeySecret替换就可以正常运行,但是我又栽了很久。
注意 os.Getenv()
os.Getenv()
os.Getenv()
os.Getenv():用来获取环境变量中的值。
所以这里并不能直接在代码里修改ALIBABA_CLOUD_ACCESS_KEY_ID
和ALIBABA_CLOUD_ACCESS_KEY_SECRET
。
方法1:配置ALIBABA_CLOUD_ACCESS_KEY_ID
、ALIBABA_CLOUD_ACCESS_KEY_SECRET
环境变量。
方法2:将os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")
、os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
替换(最好不要采取这种方式,很容易泄露AccessKeyId
和AccessKeySecret
)。
然后就可以在代码上正常使用了
(二)代码思路
前面者折腾了很久,这部分写的反而比较酣畅
发送:生成验证码、发送成功后手机号与验证码暂存redis中
验证:查询redis是否匹配
在登录注册之前,先获取验证码,此时手机号与验证码会暂存在redis中。在登录注册之时只需要查询redis,即可。
1、发送
package service
import (
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
dysmsapi20170525 "github.com/alibabacloud-go/dysmsapi-20170525/v3/client"
console "github.com/alibabacloud-go/tea-console/client"
util "github.com/alibabacloud-go/tea-utils/v2/service"
"github.com/alibabacloud-go/tea/tea"
"math/rand"
"mosi-back-end/dao/redis"
"mosi-back-end/models"
"strconv"
)
const (
signName = "填自己的"
templateCode = "填自己的"
accessKeyID = "填自己的"
accessKeySecret = "填自己的"
)
// SendMsg 发送短信
func SendMsg(param *models.ParamPhoneAndAuthCode) error {
// 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378661.html
client, err := createClient(tea.String(accessKeyID), tea.String(accessKeySecret))
if err != nil {
return err
}
code := getAuthCode()
sendSmsRequest := &dysmsapi20170525.SendSmsRequest{
PhoneNumbers: tea.String(param.Phone),
SignName: tea.String(signName),
TemplateCode: tea.String(templateCode),
TemplateParam: tea.String("{\"code\":\"" + code + "\"}"),
}
runtime := &util.RuntimeOptions{}
resp, err := client.SendSmsWithOptions(sendSmsRequest, runtime)
if err != nil {
return err
}
param.AuthCode = code
// 将验证码存在redis中
if err := redis.SetAuthCode(param); err != nil {
return err
}
console.Log(util.ToJSONString(resp))
return err
}
func createClient(accessKeyId *string, accessKeySecret *string) (_result *dysmsapi20170525.Client, err error) {
config := &openapi.Config{
// 必填,您的 AccessKey ID
AccessKeyId: accessKeyId,
// 必填,您的 AccessKey Secret
AccessKeySecret: accessKeySecret,
}
// Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
config.Endpoint = tea.String("dysmsapi.aliyuncs.com")
_result = &dysmsapi20170525.Client{}
_result, err = dysmsapi20170525.NewClient(config)
return _result, err
}
// GetAuthCode 获取验证码
func getAuthCode() string {
// 生成 6 位随机数
randomNum := rand.Intn(900000) + 100000
return strconv.Itoa(randomNum)
}
2、redis设置与验证
package redis
import (
"fmt"
"go.uber.org/zap"
"mosi-back-end/models"
)
const (
overTime = 300 //超时时间
)
// SetAuthCode 设置验证码
func SetAuthCode(param *models.ParamPhoneAndAuthCode) error {
err := client.MSet(fmt.Sprintf("Msg:%v", param.Phone), fmt.Sprintf("%v", param.AuthCode)).Err()
if err != nil {
zap.L().Error("dao/redis/message.go:10", zap.Error(err))
return err
}
// 设置过期时间
client.Do("expire", fmt.Sprintf("Msg:%v", param.Phone), overTime)
return nil
}
// GetAuthCode 获取验证码
func GetAuthCode(param *models.ParamPhoneAndAuthCode) bool {
res := client.Get(fmt.Sprintf("Msg:%v", param.Phone))
if res.Val() == param.AuthCode {
return true
}
return false
}