使用 Go 构建基于 OTP 的身份验证服务器:第 3 部分
本期详细介绍了通过 Twilio 实现 OTP 传送、使用 goroutine 优化 OTP 异步发送,以及建立强大的基于令牌的身份验证系统。
使用 Twilio 发送 OTP
使用 Twilio 消息 API 发送 OTP 的核心功能如下所示:
func (app *application) sendOTPViaTwilio(otp, phoneNumber string) error { client := twilio.NewRestClientWithParams(twilio.ClientParams{ Username: os.Getenv("TWILIO_SID"), Password: os.Getenv("TWILIO_API_KEY"), }) params := &api.CreateMessageParams{} params.SetBody(fmt.Sprintf( "Thank you for choosing Cheershare! Your one-time password is %v.", otp, )) params.SetFrom(os.Getenv("TWILIO_PHONE_NUMBER")) params.SetTo(fmt.Sprintf("+91%v", phoneNumber)) const maxRetries = 3 var lastErr error for attempt := 1; attempt <= maxRetries; attempt++ { resp, err := client.SendSms(params) if err == nil { app.logger.Printf("Message SID: %s", resp.Sid) return nil } lastErr = err time.Sleep(time.Duration(attempt) * 100 * time.Millisecond) } return fmt.Errorf("failed to send OTP after %d retries: %w", maxRetries, lastErr) }
该函数利用 Twilio 的 Go SDK 发送消息。 from
号码是预先配置的 Twilio 号码。 包含重试机制以确保可靠性。
使用 Goroutine 进行异步 OTP 发送
顺序 OTP 发送会影响服务器性能。 该解决方案涉及利用 goroutine 来同时处理 OTP 传递。 application
结构已更新:
type application struct { wg sync.WaitGroup config config models data.Models logger *log.Logger cache *redis.Client }
辅助函数有助于后台任务执行:
func (app *application) background(fn func()) { app.wg.Add(1) go func() { defer app.wg.Done() defer func() { if err := recover(); err != nil { app.logger.Printf("Error in background function: %v\n", err) } }() fn() }() }
这使用 sync.WaitGroup
来管理 goroutine,确保在关闭之前完成。
数据库令牌表
创建一个新的数据库表来存储用户令牌:
-- 000002_create-token.up.sql CREATE TABLE IF NOT EXISTS tokens ( hash bytea PRIMARY KEY, user_id bigint NOT NULL REFERENCES users ON DELETE CASCADE, expiry timestamp(0) with time zone NOT NULL, scope text NOT NULL ); -- 000002_create-token.down.sql DROP TABLE IF EXISTS tokens;
该表存储哈希令牌、用户 ID、到期时间和令牌范围。 数据库迁移是使用migrate
.
代币模型和功能
data/models.go
文件包含用于令牌生成、插入和检索的函数:
// ... (other imports) ... package data // ... (other code) ... func generateToken(userId int64, ttl time.Duration, scope string) (*Token, error) { // ... (token generation logic) ... } func (m TokenModel) Insert(token *Token) error { // ... (database insertion logic) ... } func (m TokenModel) DeleteAllForUser(scope string, userID int64) error { // ... (database deletion logic) ... } func (m TokenModel) New(userId int64, ttl time.Duration, scope string) (*Token, error) { // ... (token creation and insertion logic) ... }
此代码处理令牌创建、散列和数据库交互。 New
函数创建并存储新令牌。
注册处理程序更新
cmd/api/user.go
文件的注册处理程序已修改为在成功 OTP 验证后颁发令牌:
// ... (other functions) ... func (app *application) handleUserSignupAndVerification(w http.ResponseWriter, r *http.Request) { // ... (input parsing and validation) ... // ... (OTP generation and sending logic) ... // ... (OTP verification logic) ... // ... (user creation or retrieval) ... token, err := app.generateTokenForUser(user.ID) if err != nil { // ... (error handling) ... } // ... (success response with token) ... }
这将令牌生成集成到注册流程中。
中间件层
三个中间件层增强了安全性和请求处理:recoverPanic
、authenticate
和 requireAuthenticatedUser
。 这些已实现并应用于路由,如原文所示。 上下文管理函数(contextSetUser
和 contextGetUser
)用于在请求上下文中存储和检索用户数据。
服务器配置集成了这些中间件,示例展示了如何使用requireAuthenticatedUser
保护路由。 未来的增强功能包括文件上传、正常关闭和指标集成。 完整的代码可以在 GitHub 上找到。
以上是使用 Go 构建基于 OTP 的身份验证服务器:第 3 部分的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

OpenSSL,作为广泛应用于安全通信的开源库,提供了加密算法、密钥和证书管理等功能。然而,其历史版本中存在一些已知安全漏洞,其中一些危害极大。本文将重点介绍Debian系统中OpenSSL的常见漏洞及应对措施。DebianOpenSSL已知漏洞:OpenSSL曾出现过多个严重漏洞,例如:心脏出血漏洞(CVE-2014-0160):该漏洞影响OpenSSL1.0.1至1.0.1f以及1.0.2至1.0.2beta版本。攻击者可利用此漏洞未经授权读取服务器上的敏感信息,包括加密密钥等。

后端学习路径:从前端转型到后端的探索之旅作为一名从前端开发转型的后端初学者,你已经有了nodejs的基础,...

在BeegoORM框架下,如何指定模型关联的数据库?许多Beego项目需要同时操作多个数据库。当使用Beego...

Go语言中用于浮点数运算的库介绍在Go语言(也称为Golang)中,进行浮点数的加减乘除运算时,如何确保精度是�...

Go爬虫Colly中的Queue线程问题探讨在使用Go语言的Colly爬虫库时,开发者常常会遇到关于线程和请求队列的问题。�...

Go语言中使用RedisStream实现消息队列时类型转换问题在使用Go语言与Redis...

GoLand中自定义结构体标签不显示怎么办?在使用GoLand进行Go语言开发时,很多开发者会遇到自定义结构体标签在�...

Go语言中字符串打印的区别:使用Println与string()函数的效果差异在Go...
