<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

用基于gin框架的Go語言來實現手機號發送短信驗證碼登錄

馬哥Linux運維 ? 來源:CSDN ? 作者:貓不吃魚呀 ? 2022-07-20 09:36 ? 次閱讀

現在大多數app或wap都實現了通過手機號獲取驗證碼進行驗證登錄,下面來看下用go來實現手機號發送短信驗證碼登錄的過程,基于的框架是gin 。

首先是短信服務商的申請,比如騰訊云、阿里云、網易易盾等,騰訊云自己申請個微信公眾號就行,然后申請相關的短信簽名、和短信模板,騰訊有100條試用喔。 具體的代碼實現 配置騰訊云短信服務的發送短信相關配置,具體可以參考騰訊云短信服務的api 文檔,進行配置


pYYBAGLXXCmAMMk3AABN_sggOds651.jpg
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



審核編輯:劉清


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • WAP
    WAP
    +關注

    關注

    0

    文章

    25

    瀏覽量

    34146
  • APP
    APP
    +關注

    關注

    33

    文章

    1540

    瀏覽量

    71714

原文標題:Go語言實現發送短信驗證碼并登錄

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    織夢dedecms登陸提示“驗證碼不正確”的完整解決方案

    時的驗證碼驗證步驟,具體辦法是:可以取消掉驗證碼,具體方法如下實現的方法一共分為兩步進行:打開 dede/login.php 找到:if(
    發表于 03-10 23:53

    12306圖片驗證碼難倒了誰?

    ,現在不光要靠網速……(還有看人品)下面是摘自網上的新聞:  一次性輸入正確率僅為8%  為了防止搶票軟件破解,鐵道部12306網站不斷將登錄的圖形驗證碼更新,層出不窮的圖形碼讓一些網購車票的旅客
    發表于 12-08 10:29

    論壇注冊時不顯示驗證碼

    論壇注冊時不顯示驗證碼啊,提交時提示驗證碼錯誤,希望早點解決,這是別人的發的?。。。。。。。。。?!
    發表于 03-01 21:45

    無法驗證郵箱,總是提示驗證碼錯誤,驗證碼明明是正確的。

    `無法驗證郵箱,總是提示驗證碼錯誤,驗證碼明明是正確的。是不是系統的bug?`
    發表于 05-12 10:41

    告別短信驗證時代的先驅者

    創新性身份驗證方式。1. 傳統身份驗證方式 1) 短信驗證短信驗證實現流程:一般需要用戶在注冊過
    發表于 05-27 15:02

    如何用阿里大于發送短信?

    SendSmsRequest();try{ //必填:待發送手機號。支持以逗號分隔的形式進行批量調用,批量上限為1000個手機號碼,批量調用相對于單條調用及時性稍有延遲,驗證碼類型的
    發表于 02-03 16:08

    為什么短信驗證碼在我們生活中頻頻出現

    來說選擇不同平臺的效果會有所不同。如果選擇一個低成本、效果好、安全性高、操作方便的平臺管理用戶、短信驗證碼,平臺本身具有安全性高、不泄露用戶信息等優點,對于企業來說是很重要的。而且企業短信
    發表于 04-16 23:12

    如何在KEIL單片機編程環境下實現隨機的6位數驗證碼?

    比如:單片機如何給GSM短信模塊發送一個隨機的6位數,手機收到這6位數后,通過單片機的矩陣鍵盤輸入,點亮單片機連接的一個燈(若輸入的6個數字與單片機發給手機不一樣,則燈不會亮)這個燈我
    發表于 10-22 22:20

    平臺是如何高效的破解市面上各家驗證碼平臺的各種形式驗證碼的?

    驗證碼與打平臺的對抗講起。何為打平臺?打平臺的基本原理是利用人工智能技術實現驗證碼設計原
    發表于 11-01 15:21

    【國民技術N32項目移植】手機驗證碼項目移植4--手機驗證碼計算

    ,同時看到device_id的第4個數就是驗證碼中的第4個數。四 在windows平臺計算驗證碼如下圖,把同樣的TOTP算法代碼移植到到windows平臺,編譯后,同一時間計算的驗證碼跟MCU 端一樣。實際項目中,只需要把win
    發表于 02-24 14:45

    OpenHarmony端云一體化應用開發快速入門練習(中)登錄認證

    一、登錄認證手機 可以在應用中集成手機帳號認證方式,您的用戶可以使用“手機號碼+密碼”或者“手機號碼+
    發表于 06-20 17:05

    基于加密短信驗證碼的移動安全支付解決方案

    安全認證,并且利用客戶在服務器上注冊的用戶名、密碼和加密的交易驗證短信來確保即使驗證碼密文泄漏,攻擊者也無法獲取驗證碼,從而杜絕了驗證碼泄漏
    發表于 11-29 14:40 ?0次下載
    基于加密<b class='flag-5'>短信</b><b class='flag-5'>驗證碼</b>的移動安全支付解決方案

    短信驗證碼漏洞風險多,安全系統待升級

    人在睡夢中,手機在身邊。是誰遠程偷看了短信驗證碼,還利用短信驗證碼完成了轉賬購物借貸等操作?據了解,這是不法分子通過“GSM劫持+
    發表于 08-18 11:06 ?1303次閱讀

    以一個真實網站的驗證碼為例,實現了基于一下KNN的驗證碼識別

    很多網站登錄都需要輸入驗證碼,如果要實現自動登錄就不可避免的要識別驗證碼。本文以一個真實網站的驗證碼
    的頭像 發表于 12-24 17:27 ?7455次閱讀

    一個短信驗證碼爆破重置

    以前倒是遇到過不少四位數驗證碼爆破的,但是這種可以結合短信遍歷,一個短信驗證碼只能驗證三次的,最后能成功利用的還是第一次遇到,關鍵還是這里不
    的頭像 發表于 09-07 09:14 ?4163次閱讀
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>