动态验证码简介
动态验证码(通常称为 TOTP,即 Time-based One-Time Password)是一种基于时间的一次性密码技术,用于增强用户身份验证的安全性。TOTP 是二步验证(2FA)的一种形式,广泛用于保护用户账户免受未经授权访问。
动态验证码的工作原理
-
生成密钥:在用户设置动态验证码时,系统会生成一个密钥,并将该密钥提供给用户的身份验证器应用(如 Google Authenticator、Authy 等)。这个密钥是用户身份验证的核心部分。
-
同步时间:动态验证码依赖于时间同步。系统和身份验证器应用都基于当前的时间来生成验证码。验证码的有效期通常为 30 秒,因此验证码会随着时间的推移而更换。
-
生成验证码:身份验证器应用和服务器使用相同的密钥和时间来生成验证码。用户在登录时提供的验证码必须与服务器生成的验证码匹配才能通过身份验证。
-
验证:当用户输入验证码时,服务器会使用相同的密钥和时间戳来生成验证码,并与用户输入的验证码进行比较。如果匹配,用户验证成功。
实现动态验证码的步骤
以下是如何使用 Gin
框架和 google-authenticator
库来实现一个简单的动态验证码登录系统的步骤。
1. 安装必要的库
首先,确保你已经安装了 gin
和 google-authenticator
库。打开终端并运行以下命令:
go get github.com/gin-gonic/gin
go get github.com/pquerna/otp/totp
go get github.com/skip2/go-qrcode
2. 编写 main.go
文件
创建一个名为 main.go
的文件,并添加以下代码:
package main
import (
"github.com/gin-gonic/gin"
"github.com/pquerna/otp/totp"
"net/http"
"log"
)
// 生成 TOTP 密钥的路由处理器
func generateHandler(c *gin.Context) {
key, err := totp.Generate(totp.GenerateOpts{
Issuer: "MyApp", //你的应用名称
AccountName: "user@example.com", //账号
})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
//一下代码1、2,二选一即可
//1、返回秘钥及url数据
c.JSON(http.StatusOK, gin.H{
"secret": key.Secret(),
"url": key.URL(),
})
//2、或者你可以只直接返回二维码给前端
//qrCode, err := qrcode.Encode(key.URL(), qrcode.Medium, 256)
//if err != nil {
// c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
// return
//}
// 设置响应头
//c.Header("Content-Type", "image/png")
//c.Header("Content-Disposition", "inline; filename=qr.png")
//c.Data(http.StatusOK, "image/png", qrCode)
}
// 验证 TOTP 码的路由处理器
func verifyHandler(c *gin.Context) {
var params struct {
Secret string `json:"secret"`//一般将秘钥存入数据库,根据账号查询秘钥,取出来校验
Code string `json:"code"`
}
if err := c.BindJSON(¶ms); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
valid := totp.Validate(params.Code, params.Secret)
if valid {
c.JSON(http.StatusOK, gin.H{"status": "success"})
} else {
c.JSON(http.StatusUnauthorized, gin.H{"status": "failure"})
}
}
func main() {
router := gin.Default()
router.GET("/generate", generateHandler)
router.POST("/verify", verifyHandler)
log.Fatal(router.Run(":8080"))
}
3. 启动应用并测试
-
生成 TOTP 密钥:启动你的应用程序,访问
http://localhost:8080/generate
。你将获得一个 JSON 响应,其中包含一个密钥和一个用于设置身份验证器的 URL。示例响应:
{ "secret": "JBSWY3DPEHPK3PXP", "url": "otpauth://totp/MyApp:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=MyApp" }
-
配置身份验证器:使用
url
中的链接配置你的身份验证器应用(如 Google Authenticator)。你将看到一个与密钥相关联的验证码。 -
验证 TOTP 码:使用你的身份验证器生成的验证码,发送一个 POST 请求到
http://localhost:8080/verify
,包含secret
和code
。示例
curl
请求:curl -X POST http://localhost:8080/verify \ -H "Content-Type: application/json" \ -d '{"secret": "JBSWY3DPEHPK3PXP", "code": "123456"}'
如果验证码正确,你会收到
{"status": "success"}
响应,否则会收到{"status": "failure"}
响应。
总结
动态验证码(TOTP)是一个强大的工具,用于提升应用程序的安全性。通过结合时间和密钥,它提供了一种有效的方式来防止未经授权的访问。使用 Gin
和 google-authenticator
,你可以轻松实现这种机制,保护你的用户账户安全。在博客中,你可以展示这些步骤,并强调动态验证码在现代身份验证中的重要性和优势。