使用Redis制作一个简化的验证码系统。在这个验证码系统中,Redis起到了一个核心的暂存和验证的角色。以下是详细描述该业务流程中Redis的使用逻辑:
-
验证码生成:当需要为用户生成一个验证码时,首先会使用随机算法产生一个六位数的验证码。
-
验证码存储:生成验证码后,为了使其在后续能够被验证,需要将验证码存储在某处。这就是Redis的首次关键使用场景。使用Redis而不是其他存储方法的好处是,Redis提供了超高的数据读写速度。这确保了验证码的读取和写入几乎是实时的,为用户提供了流畅的体验。当验证码被存储时,它与一个特定的用户ID关联,并设置了一个5分钟的过期时间。这意味着,经过5分钟,Redis会自动删除该验证码,这对于验证码这样的短暂性数据非常有用。
-
验证码验证:当用户输入一个验证码以完成验证时,系统需要查询之前存储的验证码并与用户输入进行比较。这是Redis的第二个关键使用场景。由于Redis的高性能特性,可以确保在毫秒级时间内检索验证码,从而为用户提供即时的验证反馈。系统会根据用户ID从Redis中获取与之关联的验证码,并与用户输入进行对比。如果匹配,则验证成功;否则,验证失败。
-
自动过期:如上所述,Redis中存储的验证码有一个5分钟的生命周期。这是通过设置Redis键的过期时间来实现的。这确保了验证码的短暂性,同时也避免了数据存储的堆积,因为过期的验证码对系统来说已经没有用处了。
Model (models/verification.go)
package models
import (
"fmt"
"math/rand"
"time"
"github.com/go-redis/redis/v8"
"golang.org/x/net/context"
)
var ctx = context.Background()
type VerificationModel struct {
rdb *redis.Client
}
func NewVerificationModel() *VerificationModel {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
DB: 0,
})
return &VerificationModel{rdb: rdb}
}
// GenerateCode 生成一个六位随机验证码
func (vm *VerificationModel) GenerateCode() string {
return fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))
}
// StoreCode 将验证码存储到Redis中
func (vm *VerificationModel) StoreCode(userID string, code string) error {
return vm.rdb.Set(ctx, userID, code, 5*time.Minute).Err()
}
// VerifyCode 验证Redis中存储的验证码是否与用户输入匹配
func (vm *VerificationModel) VerifyCode(userID string, inputCode string) bool {
storedCode, err := vm.rdb.Get(ctx, userID).Result()
if err != nil {
return false
}
return inputCode == storedCode
}
Controller (controllers/verification_controller.go)
package controllers
import (
"net/http"
"your_project/models"
"github.com/gin-gonic/gin"
)
type VerificationController struct {
model *models.VerificationModel
}
func NewVerificationController(model *models.VerificationModel) *VerificationController {
return &VerificationController{model: model}
}
// GenerateAndStoreCode 为特定用户生成并存储验证码
func (vc *VerificationController) GenerateAndStoreCode(c *gin.Context) {
userID := c.Param("userID")
code := vc.model.GenerateCode()
err := vc.model.StoreCode(userID, code)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "无法存储验证码"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "验证码已生成并存储"})
}
// VerifyUserInput 检查用户输入的验证码是否正确
func (vc *VerificationController) VerifyUserInput(c *gin.Context) {
userID := c.Param("userID")
inputCode := c.Query("code")
isValid := vc.model.VerifyCode(userID, inputCode)
if isValid {
c.JSON(http.StatusOK, gin.H{"message": "验证码正确!"})
} else {
c.JSON(http.StatusUnauthorized, gin.H{"message": "验证码错误!"})
}
}
Main (main.go)
package main
import (
"your_project/controllers"
"your_project/models"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
model := models.NewVerificationModel()
controller := controllers.NewVerificationController(model)
// Endpoints
r.GET("/generate/:userID", controller.GenerateAndStoreCode)
r.GET("/verify/:userID", controller.VerifyUserInput)
r.Run() // 默认监听8080端口
}