package middleware import ( "net/http" "strconv" "github.com/freefire/jiang13-bbs/model" "github.com/freefire/jiang13-bbs/service" "github.com/gin-gonic/gin" ) // RateLimitMiddleware 速率限制中间件(按 IP) func RateLimitMiddleware(rl *service.RateLimiter, rateType string) gin.HandlerFunc { return func(c *gin.Context) { key := rateType + ":" + c.ClientIP() if !rl.Allow(key) { c.Header("Retry-After", "60") c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{"error": "请求过于频繁,请稍后再试"}) return } c.Next() } } // RateLimitUserMiddleware 按登录用户限流(需挂在 RequireAuth 之后) func RateLimitUserMiddleware(rl *service.RateLimiter, rateType string) gin.HandlerFunc { return func(c *gin.Context) { claims := CurrentUser(c) id := "anon" if claims != nil { id = strconv.FormatUint(uint64(claims.ID), 10) } key := rateType + ":u:" + id if !rl.Allow(key) { c.Header("Retry-After", "60") c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{"error": "操作过于频繁,请稍后再试"}) return } c.Next() } } // StaffExempt 内容类频控豁免:管理角色直接放行,其余走原限流。 // 必须挂在 RequireAuth 之后(依赖 CurrentUser);角色变更会递增 // token_version 强制重登,故 JWT 内 role 可视为实时。 func StaffExempt(inner gin.HandlerFunc) gin.HandlerFunc { return func(c *gin.Context) { if claims := CurrentUser(c); claims != nil && model.IsStaff(model.Role(claims.Role)) { c.Next() return } inner(c) } }