Files
backend_v2/internal/middleware/auth.go
toom1996 2562fc4aaa update
2026-09-01 00:08:20 +08:00

81 lines
2.2 KiB
Go
Raw 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 Gin 中间件集合。
package middleware
import (
"net/http"
"strconv"
"strings"
"fashionapi/internal/pkg/jwt"
"fashionapi/internal/pkg/response"
"github.com/gin-gonic/gin"
)
// gin.Context 中存放身份信息的键。
const (
ContextUserID = "userID"
ContextUsername = "username"
)
// bearerPrefix Authorization 头的令牌前缀。
const bearerPrefix = "Bearer "
// Auth JWT 鉴权中间件:解析 Authorization: Bearer <token>,把身份写入 Context。
//
// 令牌签发器由外部注入,避免像原实现那样在每个请求里重新加载一次配置。
func Auth(manager *jwt.Manager) gin.HandlerFunc {
return func(c *gin.Context) {
requireAuth(c, manager)
}
}
// requireAuth 校验 Bearer token 并把身份信息写入 Context;失败则 401 中断。
func requireAuth(c *gin.Context, manager *jwt.Manager) {
header := c.GetHeader("Authorization")
if !strings.HasPrefix(header, bearerPrefix) {
response.AbortError(c, http.StatusUnauthorized, "missing token")
return
}
claims, err := manager.Parse(strings.TrimPrefix(header, bearerPrefix))
if err != nil {
response.AbortError(c, http.StatusUnauthorized, "invalid token")
return
}
c.Set(ContextUserID, claims.UserID)
c.Set(ContextUsername, claims.Username)
c.Next()
}
// PublicFirstPageAuth 列表接口「首页公开、翻页需登录」鉴权中间件。
//
// 仅当分页参数 page 缺失或 <= 1 时放行(无需 token),其余页要求有效的
// Authorization: Bearer <token>,否则返回 401。用于让列表首屏对游客/SEO 可见,
// 同时保留翻页 / 批量枚举的登录门槛(防爬虫直接 dump 全量)。
func PublicFirstPageAuth(manager *jwt.Manager) gin.HandlerFunc {
return func(c *gin.Context) {
if pageStr := c.Query("page"); pageStr != "" {
if n, err := strconv.Atoi(pageStr); err == nil && n > 1 {
requireAuth(c, manager) // 非首页:走完整 JWT 校验
return
}
}
c.Next() // 首页(page 缺失或 <= 1)放行
}
}
// UserIDFrom 从 Context 取出当前用户 id。
func UserIDFrom(c *gin.Context) (uint32, bool) {
v, exists := c.Get(ContextUserID)
if !exists {
return 0, false
}
id, ok := v.(uint32)
if !ok || id == 0 {
return 0, false
}
return id, true
}