Files
jiang13-bbs/backend/middleware/ratelimit.go
freefire 3e55b5d230 feat: 管理端板块管理与旧版数据导入,补充部署运营文档
- 新增管理端板块管理页面与后端接口(admin_board)
- 新增旧版数据导入:legacyimport 服务、导入面板、importusers 命令行工具
- 聊天用户卡片、板块图标等 UI 组件与界面优化
- 补充 about/公告/1Panel 部署等文档
- gitignore 排除 dist/ 构建产物与 .agents/ 本地工具目录
2026-09-24 03:37:44 +08:00

55 lines
1.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
}
}