衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

用基于gin框架的Go語言來實(shí)現(xiàn)手機(jī)號(hào)發(fā)送短信驗(yàn)證碼登錄

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

現(xiàn)在大多數(shù)app或wap都實(shí)現(xiàn)了通過手機(jī)號(hào)獲取驗(yàn)證碼進(jìn)行驗(yàn)證登錄,下面來看下用go來實(shí)現(xiàn)手機(jī)號(hào)發(fā)送短信驗(yàn)證碼登錄的過程,基于的框架是gin 。

首先是短信服務(wù)商的申請(qǐng),比如騰訊云、阿里云、網(wǎng)易易盾等,騰訊云自己申請(qǐng)個(gè)微信公眾號(hào)就行,然后申請(qǐng)相關(guān)的短信簽名、和短信模板,騰訊有100條試用喔。 具體的代碼實(shí)現(xiàn) 配置騰訊云短信服務(wù)的發(fā)送短信相關(guān)配置,具體可以參考騰訊云短信服務(wù)的api 文檔,進(jìn)行配置


pYYBAGLXXCmAMMk3AABN_sggOds651.jpg
go 這里采用的是viper進(jìn)行加載配置,相關(guān)的加載配置代碼如下 定義相關(guān)的配置結(jié)構(gòu)體,并加載到整個(gè)項(xiàng)目的總的options 配置結(jié)構(gòu)體中

// sms 發(fā)送短信的配置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: "",
}
}
// 這為項(xiàng)目總的一個(gè)options配置,項(xiàng)目啟動(dòng)的時(shí)候會(huì)將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
}
}

下面是發(fā)送驗(yàn)證碼的實(shí)現(xiàn)

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("發(fā)送短信失敗:%s,requestId:%s", err)
return false

}
logger.Info("發(fā)送短信驗(yàn)證碼成功")
return true
}

定義發(fā)送的client,這里采用function option 的編程模式來初始化發(fā)送的client.和發(fā)送的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)
}
}

創(chuàng)建發(fā)送驗(yàn)證碼的控制層,發(fā)送成功,并將此處的電話號(hào)碼和驗(yàn)證碼保存到redis緩存中,用來登錄時(shí)候的驗(yàn)證碼有效性的校驗(yàn)

func (u *userService) SendPhoneCode(ctx context.Context, phone string) bool {
// 獲取配置參數(shù)
smsSetting := global.TencenSmsSetting
phoneSet := []string{phone}
// 隨機(jī)生成6位的驗(yàn)證碼
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()
// 將驗(yàn)證碼和手機(jī)號(hào)保存到redis中
_ = u.cache.UserCaches().SetSendPhoneCodeCache(ctx, phone, randCode)
return true

}

后面是通過手機(jī)驗(yàn)證碼進(jìn)行登錄的流程

func (u *userService) LoginByPhoneCode(ctx context.Context, phone string, phoneCode string) (*model.User,error) { // 從緩存中獲取該手機(jī)號(hào)對(duì)應(yīng)的驗(yàn)證碼是否匹配 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



審核編輯:劉清


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • WAP
    WAP
    +關(guān)注

    關(guān)注

    0

    文章

    25

    瀏覽量

    34447
  • APP
    APP
    +關(guān)注

    關(guān)注

    33

    文章

    1577

    瀏覽量

    72774

原文標(biāo)題:Go語言實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼并登錄

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    告別短信驗(yàn)證時(shí)代的先驅(qū)者

    創(chuàng)新性身份驗(yàn)證方式。1. 傳統(tǒng)身份驗(yàn)證方式 1) 短信驗(yàn)證短信驗(yàn)證實(shí)現(xiàn)流程:一般需要用戶在注冊(cè)過
    發(fā)表于 05-27 15:02

    如何用阿里大于發(fā)送短信

    SendSmsRequest();try{ //必填:待發(fā)送手機(jī)號(hào)。支持以逗號(hào)分隔的形式進(jìn)行批量調(diào)用,批量上限為1000個(gè)手機(jī)號(hào)碼,批量調(diào)用相對(duì)于單條調(diào)用及時(shí)性稍有延遲,驗(yàn)證碼類型的
    發(fā)表于 02-03 16:08

    為什么短信驗(yàn)證碼在我們生活中頻頻出現(xiàn)

    來說選擇不同平臺(tái)的效果會(huì)有所不同。如果選擇一個(gè)低成本、效果好、安全性高、操作方便的平臺(tái)管理用戶、短信驗(yàn)證碼,平臺(tái)本身具有安全性高、不泄露用戶信息等優(yōu)點(diǎn),對(duì)于企業(yè)來說是很重要的。而且企業(yè)短信
    發(fā)表于 04-16 23:12

    OpenHarmony端云一體化應(yīng)用開發(fā)快速入門練習(xí)(中)登錄認(rèn)證

    一、登錄認(rèn)證手機(jī) 可以在應(yīng)用中集成手機(jī)帳號(hào)認(rèn)證方式,您的用戶可以使用“手機(jī)號(hào)碼+密碼”或者“手機(jī)號(hào)碼+驗(yàn)
    發(fā)表于 06-20 17:05

    基于加密短信驗(yàn)證碼的移動(dòng)安全支付解決方案

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

    驗(yàn)證碼能保證真的安全嗎?

    驗(yàn)證碼的世界,竟然……如此觸目驚心! 這年頭,無論支付、注冊(cè)、還是登錄各種端口,哪怕是保障用戶安全的諸多舉措
    的頭像 發(fā)表于 06-10 09:31 ?1.2w次閱讀

    短信驗(yàn)證碼漏洞風(fēng)險(xiǎn)多,安全系統(tǒng)待升級(jí)

    人在睡夢(mèng)中,手機(jī)在身邊。是誰遠(yuǎn)程偷看了短信驗(yàn)證碼,還利用短信驗(yàn)證碼完成了轉(zhuǎn)賬購物借貸等操作?據(jù)了解,這是不法分子通過“GSM劫持+
    發(fā)表于 08-18 11:06 ?1470次閱讀

    GSM協(xié)議漏洞被非法利用 “短信驗(yàn)證碼”還安全嗎

    最近,手機(jī)有時(shí)無緣無故地收到短信驗(yàn)證碼,但是本人并未進(jìn)行任何操作。網(wǎng)上一查,發(fā)現(xiàn)這極有可能是最近鬧得沸沸揚(yáng)揚(yáng)的“截獲短信驗(yàn)證碼盜刷案”。
    的頭像 發(fā)表于 09-08 09:04 ?4344次閱讀

    以一個(gè)真實(shí)網(wǎng)站的驗(yàn)證碼為例,實(shí)現(xiàn)了基于一下KNN的驗(yàn)證碼識(shí)別

    很多網(wǎng)站登錄都需要輸入驗(yàn)證碼,如果要實(shí)現(xiàn)自動(dòng)登錄就不可避免的要識(shí)別驗(yàn)證碼。本文以一個(gè)真實(shí)網(wǎng)站的驗(yàn)證碼
    的頭像 發(fā)表于 12-24 17:27 ?7820次閱讀

    黑客虛假谷歌驗(yàn)證碼針對(duì)銀行發(fā)送惡意軟件

    黑客針對(duì)一家波蘭銀行,利用虛假谷歌reCAPTCHA驗(yàn)證碼發(fā)送惡意軟件。
    的頭像 發(fā)表于 02-25 10:01 ?3437次閱讀

    拖動(dòng)驗(yàn)證碼的具體實(shí)現(xiàn)

    .驗(yàn)證碼的一個(gè)功能就是規(guī)避機(jī)器的自動(dòng)操作,所以我們需要通過軌跡判斷這個(gè)拖動(dòng)過程是真實(shí)的人還是機(jī)器,因此我們需要記錄拖動(dòng)的路徑,路徑經(jīng)過計(jì)算之后可以發(fā)送到后端進(jìn)行進(jìn)一步的分類,比如對(duì)
    的頭像 發(fā)表于 07-18 11:02 ?6871次閱讀
    拖動(dòng)<b class='flag-5'>驗(yàn)證碼</b>的具體<b class='flag-5'>實(shí)現(xiàn)</b>

    爬蟲實(shí)現(xiàn)目標(biāo)網(wǎng)站驗(yàn)證碼登陸

    在爬蟲訪問目標(biāo)網(wǎng)站的過程中,很多網(wǎng)站為了避免被惡意訪問,需要設(shè)置驗(yàn)證碼登錄,這樣是為了避免非人類的訪問。今天我們學(xué)習(xí)下如何使用Python爬蟲實(shí)現(xiàn)驗(yàn)證碼
    發(fā)表于 12-11 15:27 ?2456次閱讀

    一個(gè)短信驗(yàn)證碼爆破重置

    以前倒是遇到過不少四位數(shù)驗(yàn)證碼爆破的,但是這種可以結(jié)合短信遍歷,一個(gè)短信驗(yàn)證碼只能驗(yàn)證三次的,最后能成功利用的還是第一次遇到,關(guān)鍵還是這里不
    的頭像 發(fā)表于 09-07 09:14 ?5164次閱讀

    Java 中驗(yàn)證碼的使用

    今天我們講一下在 Java 中驗(yàn)證碼的使用。 驗(yàn)證碼生成 本效果是利用easy-captcha工具包實(shí)現(xiàn),首先需要添加相關(guān)依賴到pom.xml中,代碼如下: com .github.whvcse
    的頭像 發(fā)表于 09-25 11:11 ?1109次閱讀
    Java 中<b class='flag-5'>驗(yàn)證碼</b>的使用

    SpringBoot分布式驗(yàn)證碼登錄方案

    傳統(tǒng)的項(xiàng)目大都是基于session交互的,前后端都在一個(gè)項(xiàng)目里面,比如傳統(tǒng)的SSH項(xiàng)目或者一些JSP系統(tǒng),當(dāng)前端頁面觸發(fā)到獲取驗(yàn)證碼請(qǐng)求,可以將驗(yàn)證碼里面的信息存在上下文中,所以登錄的時(shí)候只需要 用戶名、密碼、
    的頭像 發(fā)表于 10-12 17:34 ?764次閱讀
    SpringBoot分布式<b class='flag-5'>驗(yàn)證碼</b><b class='flag-5'>登錄</b>方案
    华盛顿百家乐官网的玩法技巧和规则| 玩百家乐技巧博客| 网络百家乐| k7娱乐城备用网址| 百家乐官网网上投注系统| 百家乐合理的投注法| 澳门足球博彩官网| 名仕百家乐官网的玩法技巧和规则| 反赌百家乐的玩法技巧和规则| 百家乐官网投注办法| 24分金| 大发888官网游戏平台| 百家乐官网公开| 泰山百家乐的玩法技巧和规则| 百家乐官网客户端LV| 百家乐21点桌| 呼图壁县| 开心8百家乐游戏| 太子娱乐城开户| 网上百家乐博彩正网| 海盐县| 网上百家乐庄家有赌场优势吗| 册亨县| 百家乐真人斗地主| 百家乐官网真人游戏网上投注 | 百家乐官网闲庄概率| 百家乐赢家| 百家乐官网视频游戏中心| 678百家乐博彩娱乐场开户注册 | 广州百家乐赌博机| 百家乐官网是骗人吗| 百家乐的出千手法| 至尊百家乐官网奇热| 威尼斯人娱乐网址| 网上赌百家乐官网的玩法技巧和规则| 大发888.com| 1月24进房子风水好吗| 民县| 大世界百家乐赌场娱乐网规则| 百家乐官网长庄投注 | 百家乐官网路单|