| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- package middleware
- import (
- "net/http"
- "time"
- "github.com/gin-contrib/sessions"
- "github.com/gin-gonic/gin"
- )
- const (
- // SecureVerificationSessionKey 安全验证的 session key(与 controller 保持一致)
- SecureVerificationSessionKey = "secure_verified_at"
- // SecureVerificationTimeout 验证有效期(秒)
- SecureVerificationTimeout = 300 // 5分钟
- )
- // SecureVerificationRequired 安全验证中间件
- // 检查用户是否在有效时间内通过了安全验证
- // 如果未验证或验证已过期,返回 401 错误
- func SecureVerificationRequired() gin.HandlerFunc {
- return func(c *gin.Context) {
- // 检查用户是否已登录
- userId := c.GetInt("id")
- if userId == 0 {
- c.JSON(http.StatusUnauthorized, gin.H{
- "success": false,
- "message": "未登录",
- })
- c.Abort()
- return
- }
- // 检查 session 中的验证时间戳
- session := sessions.Default(c)
- verifiedAtRaw := session.Get(SecureVerificationSessionKey)
- if verifiedAtRaw == nil {
- c.JSON(http.StatusForbidden, gin.H{
- "success": false,
- "message": "需要安全验证",
- "code": "VERIFICATION_REQUIRED",
- })
- c.Abort()
- return
- }
- verifiedAt, ok := verifiedAtRaw.(int64)
- if !ok {
- // session 数据格式错误
- session.Delete(SecureVerificationSessionKey)
- _ = session.Save()
- c.JSON(http.StatusForbidden, gin.H{
- "success": false,
- "message": "验证状态异常,请重新验证",
- "code": "VERIFICATION_INVALID",
- })
- c.Abort()
- return
- }
- // 检查验证是否过期
- elapsed := time.Now().Unix() - verifiedAt
- if elapsed >= SecureVerificationTimeout {
- // 验证已过期,清除 session
- session.Delete(SecureVerificationSessionKey)
- _ = session.Save()
- c.JSON(http.StatusForbidden, gin.H{
- "success": false,
- "message": "验证已过期,请重新验证",
- "code": "VERIFICATION_EXPIRED",
- })
- c.Abort()
- return
- }
- // 验证有效,继续处理请求
- c.Next()
- }
- }
- // OptionalSecureVerification 可选的安全验证中间件
- // 如果用户已验证,则在 context 中设置标记,但不阻止请求继续
- // 用于某些需要区分是否已验证的场景
- func OptionalSecureVerification() gin.HandlerFunc {
- return func(c *gin.Context) {
- userId := c.GetInt("id")
- if userId == 0 {
- c.Set("secure_verified", false)
- c.Next()
- return
- }
- session := sessions.Default(c)
- verifiedAtRaw := session.Get(SecureVerificationSessionKey)
- if verifiedAtRaw == nil {
- c.Set("secure_verified", false)
- c.Next()
- return
- }
- verifiedAt, ok := verifiedAtRaw.(int64)
- if !ok {
- c.Set("secure_verified", false)
- c.Next()
- return
- }
- elapsed := time.Now().Unix() - verifiedAt
- if elapsed >= SecureVerificationTimeout {
- session.Delete(SecureVerificationSessionKey)
- _ = session.Save()
- c.Set("secure_verified", false)
- c.Next()
- return
- }
- c.Set("secure_verified", true)
- c.Set("secure_verified_at", verifiedAt)
- c.Next()
- }
- }
- // ClearSecureVerification 清除安全验证状态
- // 用于用户登出或需要强制重新验证的场景
- func ClearSecureVerification(c *gin.Context) {
- session := sessions.Default(c)
- session.Delete(SecureVerificationSessionKey)
- _ = session.Save()
- }
|