// Package auth 管理端 JWT:签发与校验,使用 Authorization: Bearer package auth import ( "net/http" "strings" "time" "github.com/golang-jwt/jwt/v5" ) const adminJWTExpire = 7 * 24 * time.Hour // 7 天 // AdminClaims 管理端 JWT 载荷 type AdminClaims struct { jwt.RegisteredClaims Username string `json:"username"` Role string `json:"role"` } // IssueAdminJWT 签发管理端 JWT,使用 ADMIN_SESSION_SECRET 签名(role 为空时默认 admin) func IssueAdminJWT(secret, username, role string) (string, error) { if role == "" { role = "admin" } now := time.Now() claims := AdminClaims{ RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(now.Add(adminJWTExpire)), IssuedAt: jwt.NewNumericDate(now), Subject: "admin", }, Username: username, Role: role, } tok := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return tok.SignedString([]byte(secret)) } // ParseAdminJWT 校验并解析 JWT,返回 claims;无效或过期返回 nil, false func ParseAdminJWT(tokenString, secret string) (*AdminClaims, bool) { if tokenString == "" || secret == "" { return nil, false } tok, err := jwt.ParseWithClaims(tokenString, &AdminClaims{}, func(t *jwt.Token) (interface{}, error) { return []byte(secret), nil }, jwt.WithValidMethods([]string{"HS256"})) if err != nil || !tok.Valid { return nil, false } claims, ok := tok.Claims.(*AdminClaims) if !ok || claims.Username == "" { return nil, false } return claims, true } // GetAdminJWTFromRequest 从请求中读取 JWT:优先 Authorization: Bearer ,其次 Cookie admin_session(兼容旧端) func GetAdminJWTFromRequest(r *http.Request) string { // 1. Authorization: Bearer ah := r.Header.Get("Authorization") if strings.HasPrefix(ah, "Bearer ") { return strings.TrimSpace(ah[7:]) } // 2. Cookie(兼容:若值为 JWT 格式则可用) c, err := r.Cookie(adminCookieName) if err != nil || c == nil { return "" } return strings.TrimSpace(c.Value) }