Documentation
¶
Index ¶
- Constants
- Variables
- func APIRateLimit() gin.HandlerFunc
- func APIRedisRateLimit() gin.HandlerFunc
- func AdminRequired() gin.HandlerFunc
- func AnyUserRequired() gin.HandlerFunc
- func AuthRequired() gin.HandlerFunc
- func CORS() gin.HandlerFunc
- func CORSForAPI() gin.HandlerFunc
- func CORSWithConfig(corsCfg *config.CORSConfig) gin.HandlerFunc
- func CORSWithOrigins(origins []string) gin.HandlerFunc
- func CORSWithWildcard() gin.HandlerFunc
- func CSRF(config ...CSRFConfig) gin.HandlerFunc
- func CSRFExempt() gin.HandlerFunc
- func CSRFForAPI() gin.HandlerFunc
- func CSRFToken(c *gin.Context)
- func CSRFWithExempt(config ...CSRFConfig) gin.HandlerFunc
- func CSRFWithSkip(skipPaths []string) gin.HandlerFunc
- func CustomRateLimit(rate int, window time.Duration) gin.HandlerFunc
- func CustomRedisRateLimit(keyPrefix string, rate int, window time.Duration) gin.HandlerFunc
- func CustomRedisRateLimitFailClosed(keyPrefix string, rate int, window time.Duration) gin.HandlerFunc
- func DoubleSubmitCookie() gin.HandlerFunc
- func GenerateAPIToken(c *gin.Context)
- func GetCSRFToken(c *gin.Context) string
- func GetRequestID(c *gin.Context) string
- func GetRole(c *gin.Context) string
- func GetUserID(c *gin.Context) uint
- func GetUserType(c *gin.Context) string
- func GetUsername(c *gin.Context) string
- func InitRateLimiters()
- func Logger() gin.HandlerFunc
- func LoggerForAPI() gin.HandlerFunc
- func LoggerForDebug() gin.HandlerFunc
- func LoggerMinimal() gin.HandlerFunc
- func LoggerWithConfig(cfg LoggerConfig) gin.HandlerFunc
- func LoginRateLimit() gin.HandlerFunc
- func LoginRedisRateLimit() gin.HandlerFunc
- func Metrics() gin.HandlerFunc
- func RateLimit(limiter *RateLimiter) gin.HandlerFunc
- func Recover() gin.HandlerFunc
- func RecoverWithDetail() gin.HandlerFunc
- func RedisRateLimit(keyPrefix string, rate int) gin.HandlerFunc
- func RedisRateLimitFailClosed(keyPrefix string, rate int) gin.HandlerFunc
- func RedisRateLimitWithIdentifier(keyPrefix string, rate int, identifierFunc func(c *gin.Context) string) gin.HandlerFunc
- func RequestID() gin.HandlerFunc
- func RequireAuth(checker AuthChecker, messages ...string) gin.HandlerFunc
- func RequireRoles(roles ...string) gin.HandlerFunc
- func RequireUserTypes(userTypes ...string) gin.HandlerFunc
- func StaffRequired() gin.HandlerFunc
- func StopRateLimiters()
- func SuperAdminRequired() gin.HandlerFunc
- func Timeout(d time.Duration) gin.HandlerFunc
- func UploadRateLimit() gin.HandlerFunc
- func UploadRedisRateLimit() gin.HandlerFunc
- type AuthChecker
- type AuthUser
- type CSRFConfig
- type LoggerConfig
- type RateLimiter
- type RedisRateLimiter
- func (rl *RedisRateLimiter) Allow(ctx context.Context, identifier string) (bool, error)
- func (rl *RedisRateLimiter) GetCount(ctx context.Context, identifier string) (int64, error)
- func (rl *RedisRateLimiter) Reset(ctx context.Context, identifier string) error
- func (rl *RedisRateLimiter) SetFailClosed(failClosed bool)
Constants ¶
const ( // ContextKeyUserID 用户ID上下文键 ContextKeyUserID = "user_id" // ContextKeyUsername 用户名上下文键 ContextKeyUsername = "username" // ContextKeyRole 角色上下文键 ContextKeyRole = "role" // ContextKeyUserType 用户类型上下文键 ContextKeyUserType = "user_type" // DefaultUserTypeSuperAdmin 默认超级管理员用户类型 DefaultUserTypeSuperAdmin = "super_admin" // DefaultUserTypeAdmin 默认管理员用户类型 DefaultUserTypeAdmin = "admin" // DefaultUserTypeStaff 默认员工用户类型 DefaultUserTypeStaff = "staff" )
const ( // CSRFTokenLength CSRF Token 长度 CSRFTokenLength = 32 // CSRFHeaderName CSRF Header 名称 CSRFHeaderName = "X-CSRF-Token" // CSRFCookieName CSRF Cookie 名称 CSRFCookieName = "csrf_token" // CSRFFormField 表单字段名称 CSRFFormField = "_csrf" )
Variables ¶
var ( // fail-closed 限流器在此情况下拒绝请求;fail-open 限流器放行。 ErrRedisRateLimiterUnavailable = errors.New("redis rate limiter: redis client unavailable") // ErrRedisRateLimiterUnexpectedResult Redis 返回非预期的结果类型(非 int64)。 // fail-closed 限流器拒绝;fail-open 限流器放行。旧实现裸断言会 panic。 ErrRedisRateLimiterUnexpectedResult = errors.New("redis rate limiter: unexpected result type") )
H4c: Redis 限流器故障相关错误。
var DefaultCSRFConfig = CSRFConfig{ TokenLength: CSRFTokenLength, HeaderName: CSRFHeaderName, CookieName: CSRFCookieName, FormField: CSRFFormField, Secure: false, HTTPOnly: true, SameSite: http.SameSiteLaxMode, Path: "/", MaxAge: 3600, ErrorFunc: defaultCSRFError, SkipFunc: nil, }
DefaultCSRFConfig 默认 CSRF 配置
var DefaultLoggerConfig = LoggerConfig{ LogRequestBody: false, LogResponseBody: false, MaxBodyLength: 1024, SkipPaths: []string{"/health", "/swagger"}, SkipPathPrefixes: []string{"/public", "/static"}, SlowRequestThreshold: 500 * time.Millisecond, }
DefaultLoggerConfig 默认日志配置
Functions ¶
func APIRedisRateLimit ¶
func APIRedisRateLimit() gin.HandlerFunc
APIRedisRateLimit API Redis 分布式限流(fail-open,避免影响业务)。
func AnyUserRequired ¶
func AnyUserRequired() gin.HandlerFunc
AnyUserRequired 任意用户权限中间件(默认允许 admin/super_admin/staff)
func CORS ¶
func CORS() gin.HandlerFunc
CORS 跨域中间件 支持从配置文件读取 CORS 配置;遵循 W3C CORS 规范: 当 AllowCredentials=true 时,Access-Control-Allow-Origin 必须回显为具体 Origin, 不能使用 "*"(浏览器会拒绝携带凭证的响应)。
func CORSWithConfig ¶
func CORSWithConfig(corsCfg *config.CORSConfig) gin.HandlerFunc
CORSWithConfig 使用自定义配置的 CORS 中间件
func CORSWithOrigins ¶
func CORSWithOrigins(origins []string) gin.HandlerFunc
CORSWithOrigins 使用指定域名列表的 CORS 中间件
func CORSWithWildcard ¶
func CORSWithWildcard() gin.HandlerFunc
CORSWithWildcard 允许所有来源的 CORS 中间件(仅用于开发环境) 注意:生产环境不建议使用
func CSRFForAPI ¶
func CSRFForAPI() gin.HandlerFunc
CSRFForAPI 适用于 API 的 CSRF 中间件(不使用 Cookie) 客户端需要先调用 GenerateAPIToken 获取 Token,随后在每个非安全方法请求的 X-CSRF-Token 头中携带。Token 单次消费(验证通过即删除)且受 TTL 约束, 防止重放与内存无限增长。
注意:存储为进程内内存,仅适用于单实例部署。多实例请自行用 Redis SETEX + GETDEL 实现等价语义。
func CSRFWithExempt ¶
func CSRFWithExempt(config ...CSRFConfig) gin.HandlerFunc
CSRFWithExempt 支持 exempt 标记的 CSRF 中间件
func CSRFWithSkip ¶
func CSRFWithSkip(skipPaths []string) gin.HandlerFunc
CSRFWithSkip 跳过指定路径的 CSRF 检查
func CustomRateLimit ¶
func CustomRateLimit(rate int, window time.Duration) gin.HandlerFunc
CustomRateLimit 自定义速率限制(内存版)
创建的限流器登记入包级 customLimiters 表,StopRateLimiters / InitRateLimiters 会统一停止其 cleanup goroutine(H4b 修复:原实现每次路由构造创建 limiter 无句柄, StopRateLimiters 不感知 → cleanup goroutine 泄漏)。
func CustomRedisRateLimit ¶
CustomRedisRateLimit 自定义 Redis 分布式限流(fail-open)。
func CustomRedisRateLimitFailClosed ¶ added in v1.2.0
func CustomRedisRateLimitFailClosed(keyPrefix string, rate int, window time.Duration) gin.HandlerFunc
CustomRedisRateLimitFailClosed 自定义安全型 Redis 分布式限流(fail-closed)。
func DoubleSubmitCookie ¶
func DoubleSubmitCookie() gin.HandlerFunc
DoubleSubmitCookie 双重提交 Cookie 模式(无需服务器存储) 适用于无状态 API
func GenerateAPIToken ¶
GenerateAPIToken 生成 API CSRF Token(用于 API 模式) 颁发的 Token 写入进程内存储,供 CSRFForAPI 校验。
func LoggerWithConfig ¶
func LoggerWithConfig(cfg LoggerConfig) gin.HandlerFunc
LoggerWithConfig 使用自定义配置的日志中间件
func LoginRedisRateLimit ¶
func LoginRedisRateLimit() gin.HandlerFunc
LoginRedisRateLimit 登录接口 Redis 分布式限流(fail-closed)。
H4c: 登录防爆破场景必须 fail-closed——Redis 故障时若 fail-open 则限流失效、 攻击者可借 Redis 抖动窗口无限爆破。改为 fail-closed:Redis 故障时返 503 拒绝。
func Metrics ¶ added in v1.1.0
func Metrics() gin.HandlerFunc
Metrics Prometheus 指标中间件(#18)。记录请求计数、耗时、在飞数。 route 标签用 c.FullPath()(路由模板,如 /api/v1/users/:id),避免高基数。
func RecoverWithDetail ¶
func RecoverWithDetail() gin.HandlerFunc
RecoverWithDetail panic恢复中间件(详细版本,返回更多信息) 注意: 生产环境不应使用,会暴露敏感信息
func RedisRateLimit ¶
func RedisRateLimit(keyPrefix string, rate int) gin.HandlerFunc
RedisRateLimit Redis 分布式限流中间件(fail-open:Redis 故障时放行,避免影响业务)。 参数: keyPrefix 键名前缀(如 "login_limit"),rate 每分钟请求数 安全敏感场景(登录防爆破等)应使用 RedisRateLimitFailClosed,Redis 故障时拒绝以防限流失效。
func RedisRateLimitFailClosed ¶ added in v1.2.0
func RedisRateLimitFailClosed(keyPrefix string, rate int) gin.HandlerFunc
RedisRateLimitFailClosed 安全型 Redis 分布式限流中间件(fail-closed): Redis 故障时拒绝(503),避免限流静默失效。用于登录防爆破等安全场景。
func RedisRateLimitWithIdentifier ¶
func RedisRateLimitWithIdentifier(keyPrefix string, rate int, identifierFunc func(c *gin.Context) string) gin.HandlerFunc
RedisRateLimitWithIdentifier 自定义标识的 Redis 分布式限流(fail-open)。 参数: keyPrefix 键名前缀,rate 每分钟请求数,identifierFunc 标识获取函数
func RequestID ¶
func RequestID() gin.HandlerFunc
RequestID 请求ID中间件,为每个请求生成唯一ID便于追踪。
客户端可经 X-Request-ID 头传入 ID 用于链路串联,但会做校验(M15 修复): 仅接受可见 ASCII、无换行、长度 ≤128 的值,否则忽略并重新生成——防头注入与日志伪造。
func RequireAuth ¶
func RequireAuth(checker AuthChecker, messages ...string) gin.HandlerFunc
RequireAuth 自定义权限中间件
func RequireUserTypes ¶
func RequireUserTypes(userTypes ...string) gin.HandlerFunc
RequireUserTypes 用户类型权限中间件
func Timeout ¶ added in v1.1.0
func Timeout(d time.Duration) gin.HandlerFunc
Timeout 请求级超时中间件(#19)。
与 http.Server.ReadTimeout(连接级)不同,这是业务级超时: 为每个请求的 context 设置 deadline,下游 GORM / Redis / HTTP 调用 走 c.Request.Context() 即可级联取消,避免单个慢请求拖垮协程。
⚠️ 软超时语义(M14 文档化):本中间件仅注入带 deadline 的 ctx,不会主动中断 handler。 生效前提是下游实际消费 ctx——GORM/Redis/HTTP 客户端等会响应 ctx 取消;但若 handler 是纯 CPU 循环、阻塞于不查 ctx 的调用、或不读 c.Request.Context(),则 deadline 到期 也不会停。需要硬中断的场景请配合 http.Server.WriteTimeout 或在 handler 内显式 select ctx.Done。
用法:
r.Use(middleware.Timeout(5 * time.Second))
d <= 0 时不启用超时(直接 Next)。
func UploadRedisRateLimit ¶
func UploadRedisRateLimit() gin.HandlerFunc
UploadRedisRateLimit 上传接口 Redis 分布式限流(fail-open)。
Types ¶
type CSRFConfig ¶
type CSRFConfig struct {
// TokenLength Token 长度
TokenLength int
// HeaderName Header 名称
HeaderName string
// CookieName Cookie 名称
CookieName string
// FormField 表单字段名
FormField string
// Secure Cookie 是否启用 Secure
Secure bool
// HTTPOnly Cookie 是否启用 HttpOnly
HTTPOnly bool
// SameSite Cookie SameSite 属性
SameSite http.SameSite
// Domain Cookie 域名
Domain string
// Path Cookie 路径
Path string
// MaxAge Cookie 有效期(秒)
MaxAge int
// ErrorFunc 错误处理函数
ErrorFunc func(c *gin.Context)
// SkipFunc 跳过检查函数
SkipFunc func(c *gin.Context) bool
}
CSRFConfig CSRF 配置
type LoggerConfig ¶
type LoggerConfig struct {
// LogRequestBody 是否记录请求体
LogRequestBody bool
// LogResponseBody 是否记录响应体
LogResponseBody bool
// MaxBodyLength 最大记录的请求/响应体长度(字节)
MaxBodyLength int
// SkipPaths 不记录日志的路径
SkipPaths []string
// SkipPathPrefixes 不记录日志的路径前缀
SkipPathPrefixes []string
// SlowRequestThreshold 慢请求阈值(超过此时间记录警告)
SlowRequestThreshold time.Duration
}
LoggerConfig 日志中间件配置
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter 速率限制器(内存版,单实例使用)
func NewRateLimiter ¶
func NewRateLimiter(rate int, window time.Duration) *RateLimiter
NewRateLimiter 创建速率限制器(内存版)
func (*RateLimiter) Allow ¶
func (rl *RateLimiter) Allow(ip string) bool
Allow 检查是否允许请求。
固定窗口语义(H4a 修复):windowStart 是当前窗口起点,仅在窗口过期重置时变更; 放行时不再更新 windowStart。窗口内 count 达到 rate 即拒绝,窗口过期则重置为新窗口。 旧实现每次放行更新 lastSeen,致重置分支对持续客户端永不成立、稳态客户端被误限流。
注意:固定窗口算法允许窗口边界突发(两窗口交界处瞬时可达 2×rate)。 如需平滑限流(无突发),请用 Redis 版 RedisRateLimiter(滑动窗口)。
func (*RateLimiter) SetNowFunc ¶ added in v1.2.0
func (rl *RateLimiter) SetNowFunc(f func() time.Time)
SetNowFunc 注入时间源(默认 time.Now),供测试用可控时钟验证窗口语义。 生产代码通常无需调用。
type RedisRateLimiter ¶
type RedisRateLimiter struct {
// contains filtered or unexported fields
}
RedisRateLimiter Redis 分布式限流器
func NewRedisRateLimiter ¶
func NewRedisRateLimiter(keyPrefix string, rate int, window time.Duration) *RedisRateLimiter
NewRedisRateLimiter 创建 Redis 分布式限流器(默认 fail-open:Redis 错误时放行,避免影响业务)。 安全敏感场景(如登录防爆破)应使用 NewRedisRateLimiterFailClosed,Redis 故障时拒绝以防限流失效。
func NewRedisRateLimiterFailClosed ¶ added in v1.2.0
func NewRedisRateLimiterFailClosed(keyPrefix string, rate int, window time.Duration) *RedisRateLimiter
NewRedisRateLimiterFailClosed 创建安全型 Redis 分布式限流器(fail-closed): Redis 不可用/错误/返回非预期类型时拒绝请求,避免限流静默失效(防爆破场景必备)。
func (*RedisRateLimiter) Allow ¶
Allow 检查是否允许请求。
H4c 修复:
- result.(int64) 改 comma-ok,断言失败返 ErrRedisRateLimiterUnexpectedResult 而非 panic。
- Redis 错误/断言失败时按 failClosed 策略决定:fail-closed 返 (false, err) 拒绝, fail-open 返 (true, err) 放行(兼容旧行为)。中间件层据此 allowed 值决定放行/拒绝, 不再无条件 fail-open——登录防爆破等安全场景用 fail-closed 限流器即可在 Redis 故障时拒绝。
Redis 未启用(database.GetRedis() == nil)时:fail-closed 返 (false, ErrRedisRateLimiterUnavailable), fail-open 返 (true, nil)(兼容旧行为)。安全场景必须确保 Redis 已启用。
func (*RedisRateLimiter) Reset ¶
func (rl *RedisRateLimiter) Reset(ctx context.Context, identifier string) error
Reset 重置限流计数
func (*RedisRateLimiter) SetFailClosed ¶ added in v1.2.0
func (rl *RedisRateLimiter) SetFailClosed(failClosed bool)
SetFailClosed 设置 Redis 故障时的策略:true=拒绝(安全型),false=放行(兼容默认)。 供已创建的限流器切换策略。并发安全(atomic.Store),可与并发 Allow 调用共存。