【后端学习笔记·Golang】邮箱邮件验证

本文介绍了如何使用Goframe框架实现邮箱登录验证功能,包括生成随机验证码、通过gomail发送验证码到用户邮箱以及验证用户输入的验证码过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

邮箱登陆验证

流程:

  • 接收用户请求后生成随机验证码,并将验证码存入Redis中,并设置TTL

  • 通过gomail发送验证码给用户邮箱

  • 接收用户输入的验证码,与Redis中存放的验证码进行比对

生成随机验证码

​ 随机种子通过 time.Now().UnixNano() 进行设置,以确保对于同一个用户每次请求都使用不同的种子。然后,定义了一个包含数字字符的 letters 切片。每次通过 rand.Intn(len(letters)) 随机选择 letters 切片中的一个字符,并将其存储在 b 中。最后,将 b 转换为字符串并返回。

import (
	"math/rand"
	"time"
)
func GenerateRandomCode(length int) string {
	rand.Seed(time.Now().UnixNano())
	var letters = []rune("0123456789")
	b := make([]rune, length)
	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}

向用户邮箱发送验证码

  • 这里使用了gomail进行发送邮箱验证码。gomail package - gopkg.in/gomail.v2 - Go Packages
  • 此处密码为授权码而非登陆密码,以qq为例:需要在邮箱设置->账号安全->POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务处开启服务,然后获取授权码
  • Host:SMTP 服务器的主机地址。
  • Port:SMTP 服务器的端口号。
  • Username:SMTP 服务器的邮箱账号。
  • Password:SMTP 服务器的密码。
# qq邮箱
host: smtp.qq.com
port: 587
username: ********@qq.com
password: ********
// 发送邮箱验证码
func EmailSendCode(ctx context.Context, email string) (code string, err error) {
	// 生成6位随机验证码
	code = vcode.GenerateRandomCode(6)
	m := gomail.NewMessage()
	m.SetHeader("From", cfg.username)
	m.SetHeader("To", email)
	m.SetHeader("Subject", "验证码")
	msg := fmt.Sprintf("您的验证码为: %s", code)
	m.SetBody("text/html", msg)
	d := gomail.NewDialer(cfg.host, cfg.port, cfg.username, cfg.password)
	err = d.DialAndSend(m)
	return
}

接口

Goframe 框架

获取验证码

​ 如果发送验证码成功,将验证码存储到 Redis 中。这里 使用SETEX 命令设置了一个键值对,键以邮箱地址为后缀,值是验证码,过期时间设置为 120 秒(2 分钟)。(Goframe框架)

func (c *ControllerV1) SendCode(ctx context.Context, req *v1.SendCodeReq) (res *v1.SendCodeRes, err error) {
	res = &v1.SendCodeRes{}
	code, err := email.EmailSendCode(ctx, req.Email)
	if err != nil {
		return
	}
    // 将验证码存入Redis中,并设置TTL
	_, err = g.Redis().Do(ctx, "SETEX", fmt.Sprintf("code.%s", req.Email), 120, code)
	if err != nil {
		return
	}
	res.States = true
	return
}

校验验证码

​ 检查请求中是否包含验证码。如果验证码非空,则从 Redis 中获取之前发送给该邮箱的验证码,并与请求中的验证码进行比较。如果验证码不匹配,则返回一个错误。验证码正确则查询用户信息,用用户的唯一标识符获取 JWT 令牌。最后,将 JWT 令牌包装在响应对象中返回。

func (c *ControllerV1) Login(ctx context.Context, req *v1.LoginReq) (res *v1.LoginRes, err error) {
	user := entity.User{
		Email:    req.Email,
	}
	if req.VerificationCode != "" {
		search, _ := g.Redis().Do(ctx, "GET", fmt.Sprintf("code.%s", req.Email))
		code := search.String()
		if code != req.VerificationCode {
			return res, gerror.New("验证码错误或未发送")
		}
	}
    // 查询用户信息
	search, err := service.User().UserInfo(ctx,user)
    if err != nil {
		return
    }
	// 保存jwt令牌
	token, _ := service.JwtStorage().GetJwtAndSave(ctx, search.Id)
	res = &v1.LoginRes{
		Token: token,
	}
	return
}
### Golang 后端开发学习路线 #### 环境准备与基础设置 安装并配置好 Go 编译环境是第一步,这包括从官方网站获取最新版本的 Go 并完成本地安装[^1]。接着需正确设定 `GOPATH` 以及启用模块化支持(通过 `go mod init` 初始化项目),以便于依赖管理和构建过程。 #### 工具链熟悉度提升 掌握至少一种主流IDE对于提高编码效率至关重要;推荐尝试 Visual Studio Code 或者 JetBrains 的 GoLand 这样的集成开发环境来辅助日常编程工作流。这些工具提供了诸如自动补全、调试器等功能,有助于加速新手成长曲线。 #### 数据结构深入理解 针对特定的数据类型如数组扩容机制和映射表 (map),应具备扎实的理解能力。例如,在遇到内存不足的情况下如何优雅地扩展底层数组大小,并确保原有数据不丢失;而对于 map,则要知道它基于哈希表实现,提供高效的键值对存取操作,平均情况下具有常数级别的访问性能 O(1)[^3]。 #### 并发控制技巧 学会利用 Goroutines 来执行异步任务是非常重要的技能之一。这是一种非常轻便的方式来进行多任务处理,只需简单加上 `go` 关键字即可启动新的协程实例。与此同时,为了保障共享资源的安全性,还需熟练运用 Channels 或内置同步原语比如 `sync.Mutex` 对象协调多个 goroutine 之间的交互行为。 #### Web 框架 Gin 掌握要点 当涉及到 RESTful API 设计时,Gin 是一个高性能的选择。该框架内部采用前缀树优化 URL 查找速度,并允许开发者灵活定义路由规则及自定义中间件逻辑[^4]。此外,还应该注意 gin 中间件的设计模式——即通过组合不同阶段的小型处理器形成完整的请求响应管道。 ```python import "github.com/gin-gonic/gin" func main() { r := gin.Default() r.GET("/hello", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "Hello world", }) }) r.Run(":8080") } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值