middleware

package
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 13, 2026 License: MIT Imports: 29 Imported by: 0

Documentation

Index

Constants

View Source
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"
)
View Source
const (
	// CSRFTokenLength CSRF Token 长度
	CSRFTokenLength = 32
	// CSRFHeaderName CSRF Header 名称
	CSRFHeaderName = "X-CSRF-Token"
	// CSRFCookieName CSRF Cookie 名称
	CSRFCookieName = "csrf_token"
	// CSRFFormField 表单字段名称
	CSRFFormField = "_csrf"
	// CSRFMaxBodyBytes JSON body 中读取 CSRF token 的最大字节数,防止 pre-auth OOM。
	CSRFMaxBodyBytes = 1 << 20 // 1 MiB
)

Variables

View Source
var (
	// ErrRedisRateLimiterUnavailable Redis 未启用(database.GetRedis() == nil)。
	// 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 限流器故障相关错误。

View Source
var DefaultCSRFConfig = CSRFConfig{
	TokenLength:  CSRFTokenLength,
	HeaderName:   CSRFHeaderName,
	CookieName:   CSRFCookieName,
	FormField:    CSRFFormField,
	Secure:       false,
	HTTPOnly:     true,
	SameSite:     http.SameSiteLaxMode,
	Path:         "/",
	MaxAge:       3600,
	MaxBodyBytes: CSRFMaxBodyBytes,
	ErrorFunc:    defaultCSRFError,
	SkipFunc:     nil,
}

DefaultCSRFConfig 默认 CSRF 配置

View Source
var DefaultLoggerConfig = LoggerConfig{
	LogRequestBody:       false,
	LogResponseBody:      false,
	MaxBodyLength:        1024,
	SkipPaths:            []string{"/health", "/swagger"},
	SkipPathPrefixes:     []string{"/public", "/static"},
	SlowRequestThreshold: 500 * time.Millisecond,
}

DefaultLoggerConfig 默认日志配置

Functions

func APIRateLimit

func APIRateLimit() gin.HandlerFunc

APIRateLimit 普通 API 速率限制。

func APIRedisRateLimit

func APIRedisRateLimit() gin.HandlerFunc

APIRedisRateLimit API Redis 分布式限流(fail-open,避免影响业务)。

func AdminRequired

func AdminRequired() gin.HandlerFunc

AdminRequired 管理员权限中间件

func AnyUserRequired

func AnyUserRequired() gin.HandlerFunc

AnyUserRequired 任意用户权限中间件(默认允许 admin/super_admin/staff)

func AuthRequired

func AuthRequired() gin.HandlerFunc

AuthRequired JWT 认证中间件

func CORS

func CORS() gin.HandlerFunc

CORS 跨域中间件 支持从配置文件读取 CORS 配置;遵循 W3C CORS 规范: 当 AllowCredentials=true 时,Access-Control-Allow-Origin 必须回显为具体 Origin, 不能使用 "*"(浏览器会拒绝携带凭证的响应)。

func CORSForAPI

func CORSForAPI() gin.HandlerFunc

CORSForAPI 适用于 API 的 CORS 中间件

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 CSRF

func CSRF(config ...CSRFConfig) gin.HandlerFunc

CSRF 创建 CSRF 中间件

func CSRFExempt

func CSRFExempt() gin.HandlerFunc

CSRFExempt 标记路由不需要 CSRF 保护 使用方法:在路由组上使用此中间件

func CSRFForAPI

func CSRFForAPI() gin.HandlerFunc

CSRFForAPI 适用于 API 的 CSRF 中间件(不使用 Cookie) 客户端需要先调用 GenerateAPIToken 获取 Token,随后在每个非安全方法请求的 X-CSRF-Token 头中携带。Token 单次消费(验证通过即删除)且受 TTL 约束, 防止重放与内存无限增长。

注意:存储为进程内内存,仅适用于单实例部署。多实例请自行用 Redis SETEX + GETDEL 实现等价语义。

func CSRFToken

func CSRFToken(c *gin.Context)

CSRFToken 返回当前请求上下文中的 CSRF Token;若上下文无 Token 则现场生成一个返回。 适用于 Cookie/双重提交模式(与 CSRF/DoubleSubmitCookie 中间件配合), 不与 CSRFForAPI 配套--API 模式的可校验 Token 请用 GenerateAPIToken 颁发。

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 自定义速率限制(内存版)。限流器在首次请求时创建并登记到当前默认 Registry(供 Stop 统一停止,避免 cleanup goroutine 泄漏,H4b)。

func CustomRedisRateLimit

func CustomRedisRateLimit(keyPrefix string, rate int, window time.Duration, opts ...RedisRateLimiterOption) gin.HandlerFunc

CustomRedisRateLimit 自定义 Redis 分布式限流。 默认 fail-open,传 WithFailClosed(true) 切换为 fail-closed。

func DoubleSubmitCookie

func DoubleSubmitCookie() gin.HandlerFunc

DoubleSubmitCookie 双重提交 Cookie 模式(无需服务器存储) 适用于无状态 API

func GenerateAPIToken

func GenerateAPIToken(c *gin.Context)

GenerateAPIToken 生成 API CSRF Token(用于 API 模式) 颁发的 Token 写入进程内存储,供 CSRFForAPI 校验。

func GetCSRFToken

func GetCSRFToken(c *gin.Context) string

GetCSRFToken 从上下文获取 CSRF Token

func GetRequestID

func GetRequestID(c *gin.Context) string

GetRequestID 从上下文获取请求ID

func GetRole

func GetRole(c *gin.Context) string

GetRole 从上下文获取角色

func GetUserID

func GetUserID(c *gin.Context) uint

GetUserID 从上下文获取用户ID

func GetUserType

func GetUserType(c *gin.Context) string

GetUserType 从上下文获取用户类型

func GetUsername

func GetUsername(c *gin.Context) string

GetUsername 从上下文获取用户名

func InitRateLimiters

func InitRateLimiters()

InitRateLimiters 初始化默认 Registry 的标准限流器(可选,不调则懒创建)。

func Logger

func Logger() gin.HandlerFunc

Logger 日志中间件(使用默认配置)

func LoggerForAPI

func LoggerForAPI() gin.HandlerFunc

LoggerForAPI API 专用日志中间件(更详细)

func LoggerForDebug

func LoggerForDebug() gin.HandlerFunc

LoggerForDebug 调试专用日志中间件(最详细)

func LoggerMinimal

func LoggerMinimal() gin.HandlerFunc

LoggerMinimal 最简日志中间件(只记录基本信息)

func LoggerWithConfig

func LoggerWithConfig(cfg LoggerConfig) gin.HandlerFunc

LoggerWithConfig 使用自定义配置的日志中间件

func LoginRateLimit

func LoginRateLimit() gin.HandlerFunc

LoginRateLimit 登录接口速率限制。限流器在首次请求时从当前默认 Registry 懒创建, 故 App.Init swap 后用的是 App 的 Registry(避免 pre-Init 注册到 init Registry 被丢弃)。

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 RateLimit

func RateLimit(limiter *RateLimiter) gin.HandlerFunc

RateLimit 通用速率限制中间件(内存版,用户自持 limiter 时使用)。

func Recover

func Recover() gin.HandlerFunc

Recover panic恢复中间件,捕获panic并返回统一错误响应

func RecoverWithDetail

func RecoverWithDetail() gin.HandlerFunc

RecoverWithDetail panic恢复中间件(详细版本,返回更多信息) 注意: 生产环境不应使用,会暴露敏感信息

func RedisRateLimit

func RedisRateLimit(keyPrefix string, rate int, opts ...RedisRateLimiterOption) gin.HandlerFunc

RedisRateLimit Redis 分布式限流中间件。 默认 fail-open(Redis 故障时放行,避免影响业务);安全敏感场景(登录防爆破等) 传 WithFailClosed(true),Redis 故障时拒绝以防限流失效。

func RedisRateLimitWithIdentifier

func RedisRateLimitWithIdentifier(keyPrefix string, rate int, identifierFunc func(c *gin.Context) string, opts ...RedisRateLimiterOption) gin.HandlerFunc

RedisRateLimitWithIdentifier 自定义标识的 Redis 分布式限流。 参数: keyPrefix 键名前缀,rate 1 分钟窗口内允许的请求数,identifierFunc 标识获取函数。 identifierFunc 为 nil 或返回空串时回退到 c.ClientIP()。默认 fail-open,传 WithFailClosed(true) 切换。

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 RequireRoles

func RequireRoles(roles ...string) gin.HandlerFunc

RequireRoles 角色权限中间件

func RequireUserTypes

func RequireUserTypes(userTypes ...string) gin.HandlerFunc

RequireUserTypes 用户类型权限中间件

func StaffRequired

func StaffRequired() gin.HandlerFunc

StaffRequired 员工权限中间件

func StopRateLimiters

func StopRateLimiters()

StopRateLimiters 停止默认 Registry 的所有限流器。注意:仅停默认 Registry-- App 持自己的 Registry 时应在 Shutdown 调 app 自己的 Stop(Phase 5)。

func SuperAdminRequired

func SuperAdminRequired() gin.HandlerFunc

SuperAdminRequired 超级管理员权限中间件

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 UploadRateLimit

func UploadRateLimit() gin.HandlerFunc

UploadRateLimit 上传接口速率限制。

func UploadRedisRateLimit

func UploadRedisRateLimit() gin.HandlerFunc

UploadRedisRateLimit 上传接口 Redis 分布式限流(fail-closed)。 上传属资源敏感操作,Redis 故障时拒绝以防限流静默失效。

Types

type AuthChecker

type AuthChecker func(user AuthUser, c *gin.Context) bool

AuthChecker 自定义权限检查函数

type AuthUser

type AuthUser struct {
	UserID   uint
	Username string
	Role     string
	UserType string
}

AuthUser 当前认证用户

func GetAuthUser

func GetAuthUser(c *gin.Context) (AuthUser, bool)

GetAuthUser 从上下文获取认证用户

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
	// SessionCookie 为 true 时显式使用会话 Cookie(MaxAge=0)。
	// 为保持 CSRFWithConfig(CSRFConfig{}) 的默认行为,MaxAge=0 且本字段为 false 时仍使用默认 1 小时。
	SessionCookie bool
	// MaxBodyBytes 从 JSON body 提取 token 时允许读取的最大字节数。
	// <=0 时使用默认 1MiB。Header/Form token 不受此限制。
	MaxBodyBytes int64
	// 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 RateLimitRegistry added in v1.4.0

type RateLimitRegistry struct {
	// contains filtered or unexported fields
}

RateLimitRegistry 持一组内存限流器,支持 per-App 隔离。

func GetDefaultRateLimitRegistry added in v1.4.0

func GetDefaultRateLimitRegistry() *RateLimitRegistry

GetDefaultRateLimitRegistry 返回全局默认 Registry。

func NewRateLimitRegistry added in v1.4.0

func NewRateLimitRegistry() *RateLimitRegistry

NewRateLimitRegistry 创建限流器注册表实例。

func SwapDefaultRateLimitRegistry added in v1.4.0

func SwapDefaultRateLimitRegistry(r *RateLimitRegistry) *RateLimitRegistry

SwapDefaultRateLimitRegistry 置为全局默认,返回被替换的旧(照 Swap 模式)。nil 忽略,返回当前默认。

func (*RateLimitRegistry) APIRateLimit added in v1.4.0

func (r *RateLimitRegistry) APIRateLimit() gin.HandlerFunc

APIRateLimit 返回绑定到此 Registry 的普通 API 限流中间件。

func (*RateLimitRegistry) CustomRateLimit added in v1.4.0

func (r *RateLimitRegistry) CustomRateLimit(rate int, window time.Duration) gin.HandlerFunc

CustomRateLimit 返回绑定到此 Registry 的自定义限流中间件。limiter 在首次请求时创建并 登记到此 Registry(r.registerCustom),由 App.Shutdown 的 registry.Stop() 收口,无泄漏。

func (*RateLimitRegistry) Init added in v1.4.0

func (r *RateLimitRegistry) Init()

Init 预初始化标准限流器(可选;不调则首次请求时懒创建)。先停旧的同名限流器释放 goroutine。

func (*RateLimitRegistry) LoginRateLimit added in v1.4.0

func (r *RateLimitRegistry) LoginRateLimit() gin.HandlerFunc

LoginRateLimit 返回绑定到此 Registry 的登录限流中间件。

func (*RateLimitRegistry) Stop added in v1.4.0

func (r *RateLimitRegistry) Stop()

Stop 停止注册表中所有限流器(释放 cleanup goroutine)。幂等。

func (*RateLimitRegistry) UploadRateLimit added in v1.4.0

func (r *RateLimitRegistry) UploadRateLimit() gin.HandlerFunc

UploadRateLimit 返回绑定到此 Registry 的上传限流中间件。

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter 速率限制器(内存版,单实例使用)

func NewRateLimiter

func NewRateLimiter(rate int, window time.Duration) *RateLimiter

NewRateLimiter 创建速率限制器(内存版)。 rate<=0 或 window<=0 时 panic。内部启动 cleanup goroutine,调用方负责在不再使用时 调用 (*RateLimiter).Stop 释放,否则 goroutine 泄漏。

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),供测试用可控时钟验证窗口语义。 生产代码通常无需调用。

func (*RateLimiter) Stop

func (rl *RateLimiter) Stop()

Stop 停止限流器(释放资源)

type RedisRateLimiter

type RedisRateLimiter struct {
	// contains filtered or unexported fields
}

RedisRateLimiter Redis 分布式限流器

func NewRedisRateLimiter

func NewRedisRateLimiter(keyPrefix string, rate int, window time.Duration, opts ...RedisRateLimiterOption) *RedisRateLimiter

NewRedisRateLimiter 创建 Redis 分布式限流器。 默认 fail-open(Redis 故障时放行,避免影响业务);安全敏感场景传 WithFailClosed(true)。

func (*RedisRateLimiter) Allow

func (rl *RedisRateLimiter) Allow(ctx context.Context, identifier string) (bool, error)

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 未启用(redisClient() == nil)时:fail-closed 返 (false, ErrRedisRateLimiterUnavailable), fail-open 返 (true, nil)(兼容旧行为)。安全场景必须确保 Redis 已启用。

Phase 5:redisClient() 注入优先、全局兜底,App 经 WithRedisClient 注入 per-App client。

func (*RedisRateLimiter) GetCount

func (rl *RedisRateLimiter) GetCount(ctx context.Context, identifier string) (int64, error)

GetCount 获取当前窗口内的请求数

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 调用共存。

type RedisRateLimiterOption added in v1.3.0

type RedisRateLimiterOption func(*RedisRateLimiter)

RedisRateLimiterOption 配置 RedisRateLimiter 的可选策略。

func WithFailClosed added in v1.3.0

func WithFailClosed(failClosed bool) RedisRateLimiterOption

WithFailClosed 设置 Redis 故障时 fail-closed(拒绝请求)。 不传或传 false 为 fail-open(放行,兼容默认)。安全敏感场景(登录防爆破等)应传 true。

func WithRedisClient added in v1.4.0

func WithRedisClient(client *redis.Client) RedisRateLimiterOption

WithRedisClient 注入指定 Redis 客户端(Phase 5,多 Redis/测试隔离)。 不传则回退 database.GetRedis()(全局)。App 可经 app.RedisClient() 取自身 client 注入。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL