蓝莓安卓网多重安全检测下载网站、值得信赖的软件下载站!

当前位置: 蓝莓安卓网 >  教程 >  GO短信怎么用手机

GO短信怎么用手机 如何在Go语言中实现发送短信验证码并完成用户登录

时间:2023-09-17 15:43:00

小编:蓝莓安卓网

  在如今的移动互联网时代,短信验证已经成为了多数网站和应用程序的常规注册流程,而GO语言作为一门高效、简单、并发性强的编程语言,自然也有着很好的实现短信验证码的能力。通过GO语言结合第三方短信服务商的API,我们可以轻松地实现短信验证码的发送和验证,并以此作为登录的验证手段,有效提升网站和应用程序的安全性,给用户带来更加愉悦的使用体验。接下来让我们一起来探讨一下如何在GO语言中实现发送短信验证码并完成用户登录。

如何在Go语言中实现发送短信验证码并完成用户登录

GO短信怎么用手机 如何在Go语言中实现发送短信验证码并完成用户登录

首先是短信服务商的申请,比如腾讯云、阿里云、网易易盾等,腾讯云自己申请个微信公众号就行,然后申请相关的短信签名、和短信模板,腾讯有100条试用喔。

具体的代码实现

配置腾讯云短信服务的发送短信相关配置,具体可以参考腾讯云短信服务的api 文档,进行配置

sms:
  secret-key:  #秘钥,可在控制台查询
  secret-id:  #秘钥id ,可在控制台查询
  sms-sdk-app-id:  #应用id
  Sign-name:  #申请的签名
  template-id:  #模板id

go 这里采用的是viper进行加载配置,相关的加载配置代码如下

定义相关的配置结构体,并加载到整个项目的总的options 配置结构体中

// sms 发送短信的配置options
type SmsOptions struct {
SecretKey   string `json:"secret-key,omitempty" mapstructure:"secret-key"`
SecretId    string `json:"secret-id,omitempty" mapstructure:"secret-id"`
SmsSdkAppId string `json:"sms-sdk-app-id,omitempty" mapstructure:"sms-sdk-app-id"`
SignName    string `json:"sign-name,omitempty" mapstructure:"sign-name"`
TemplateId  string `json:"template-id,omitempty" mapstructure:"template-id"`
}


func NewSmsOptions() *SmsOptions {
return &SmsOptions{
SecretKey:   "",
SecretId:    "",
SmsSdkAppId: "",
SignName:    "",
TemplateId:  "",
}
}
// 这为项目总的一个options配置,项目启动的时候会将yaml中的加载到option中
type Options struct {
GenericServerRunOptions *genericoptions.ServerRunOptions `json:"server" mapstructure:"server"`
MySQLOptions *genericoptions.MySQLOptions `json:"mysql" mapstructure:"mysql"`
InsecuresServing *genericoptions.InsecureServerOptions `json:"insecure" mapstructure:"insecure"`
Log *logger.Options `json:"log" mapstructure:"log"`
RedisOptions *genericoptions.RedisOptions `json:"redis" mapstructure:"redis"`
SmsOptions *genericoptions.SmsOptions `json:"sms" mapstructure:"sms"`
}


func NewOptions() *Options  {
o:=Options{
GenericServerRunOptions: genericoptions.NewServerRunOptions(),
MySQLOptions: genericoptions.NewMySQLOptions(),
InsecuresServing: genericoptions.NewInsecureServerOptions(),
RedisOptions: genericoptions.NewRedisOptions(),
Log: logger.NewOptions(),
SmsOptions: genericoptions.NewSmsOptions(),


}
return &o
}

viper加载配置的代码如下

func AddConfigToOptions(options *options.Options) error {
viper.SetConfigName("config")
viper.AddConfigPath("config/")
viper.SetConfigType("yaml")
err := viper.ReadInConfig()
if err != nil {
return err
}


optDecode := viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(mapstructure.StringToTimeDurationHookFunc(), StringToByteSizeHookFunc()))


err = viper.Unmarshal(options, optDecode)
fmt.Println(options)
if err != nil {
return err
}
return nil
}


func StringToByteSizeHookFunc() mapstructure.DecodeHookFunc {
return func(f reflect.Type,
t reflect.Type, data interface{}) (interface{}, error) {
if f.Kind() != reflect.String {
return data, nil
}
if t != reflect.TypeOf(datasize.ByteSize(5)) {
return data, nil
}
raw := data.(string)
result := new(datasize.ByteSize)
result.UnmarshalText([]byte(raw))
return result.Bytes(), nil
}
}

下面是发送验证码的实现

type SmsClient struct {
Credential *common.Credential
Region     string
Cpf        *profile.ClientProfile
Request    SmsRequest
}

type Option func(*SmsClient)

func NewSmsClient(options ...func(client *SmsClient)) *SmsClient {
client := &SmsClient{
Region: "ap-guangzhou",
Cpf:    profile.NewClientProfile(),
}
for _, option := range options {
option(client)
}
return client

}

func WithRequest(request SmsRequest) Option {
return func(smsClient *SmsClient) {
smsClient.Request = request
}
}

func WithCredential(options options.SmsOptions) Option {
return func(smsClient *SmsClient) {
smsClient.Credential = common.NewCredential(options.SecretId, options.SecretKey)
}
}
func WithCpfReqMethod(method string) Option {
return func(smsClient *SmsClient) {
smsClient.Cpf.HttpProfile.ReqMethod = method
}
}
func WithCpfReqTimeout(timeout int) Option {
return func(smsClient *SmsClient) {
smsClient.Cpf.HttpProfile.ReqTimeout = timeout
}
}
func WithCpfSignMethod(method string) Option {
return func(smsClient *SmsClient) {
smsClient.Cpf.SignMethod = method
}
}

func (s *SmsClient) Send() bool {
sendClient, _ := sms.NewClient(s.Credential, s.Region, s.Cpf)
_, err := sendClient.SendSms(s.Request.request)
if _, ok := err.(*errors.TencentCloudSDKError); ok {
logger.Warnf("An API error has returned: %s", err)
return false
}

if err != nil {
logger.Warnf("发送短信失败:%s,requestId:%s", err)
return false

}
logger.Info("发送短信验证码成功")
return true
}

定义发送的client,这里采用function option 的编程模式来初始化发送的client.和发送的request,request的代码如下

type SmsRequest struct {
request *sms.SendSmsRequest
}

func NewSmsRequest(options *options.SmsOptions, withOptions ...func(smsRequest *SmsRequest)) *SmsRequest {
request := sms.NewSendSmsRequest()

request.SmsSdkAppId = &options.SmsSdkAppId
request.SignName = &options.SignName
request.TemplateId = &options.TemplateId
smsRequest := &SmsRequest{request: request}
for _, option := range withOptions {
option(smsRequest)
}
return smsRequest

}

type RequestOption func(*SmsRequest)

func WithPhoneNumberSet(phoneSet []string) RequestOption {
return func(smsRequest *SmsRequest) {
smsRequest.request.PhoneNumberSet = common.StringPtrs(phoneSet)
}
}

func WithTemplateParamSet(templateSet []string) RequestOption {
return func(smsRequest *SmsRequest) {
smsRequest.request.TemplateParamSet = common.StringPtrs(templateSet)
}
}

创建发送验证码的控制层,发送成功。并将此处的电话号码和验证码保存到redis缓存中,用来登录时候的验证码有效性的校验

func (u *userService) SendPhoneCode(ctx context.Context, phone string) bool {
// 获取配置参数
smsSetting := global.TencenSmsSetting
phoneSet := []string{phone}
// 随机生成6位的验证码
var randCode string = fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))
templateSet := []string{randCode, "60"}
smsRequest := tencenSms.NewSmsRequest(smsSetting, tencenSms.WithPhoneNumberSet(phoneSet), tencenSms.WithTemplateParamSet(templateSet))
smsClient := tencenSms.NewSmsClient(tencenSms.WithRequest(*smsRequest), tencenSms.WithCredential(*smsSetting))
go smsClient.Send()
// 将验证码和手机号保存到redis中
_ = u.cache.UserCaches().SetSendPhoneCodeCache(ctx, phone, randCode)
return true

}

后面是通过手机验证码进行登录的流程

func (u *userService) LoginByPhoneCode(ctx context.Context, phone string, phoneCode string) (*model.User,error) {
// 从缓存中获取该手机号对应的验证码是否匹配
cacheCode, err :=u.cache.UserCaches().GetSendPhoneCodeFromCache(ctx,phone)
if err != nil {
return nil, errors.WithCode(code.ErrUserPhoneCodeExpire,err.Error())
}
if cacheCode!=phoneCode {
return nil,errors.WithCode(code.ErrUserPhoneCodeMiss,"")
}
return &model.User{
Nickname: "lala",
}, nil


}

  在现今的互联网时代中,快速且安全地进行用户认证已成为至关重要的问题。使用GO语言实现短信验证码发送功能,能够让开发者更加方便地完成用户登录流程。同时,手机用户也可以通过简单的操作,轻松地收到验证码短信,保证账户的安全性与便利性。

相关文章

猜你喜欢

推荐游戏

更多