This repository has been archived on 2026-06-21. You can view files and clone it, but cannot push or open issues or pull requests.
Files
MetaLab/internal/middleware/admin.go

93 lines
2.6 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
import (
"log"
"net/http"
"metazone.cc/metalab/internal/common"
"metazone.cc/metalab/internal/config"
"metazone.cc/metalab/internal/model"
"metazone.cc/metalab/internal/repository"
"github.com/gin-gonic/gin"
)
// AdminAuth 管理后台页面认证中间件
// 逻辑同 AuthRequiredJWT 校验 + token_version 吊销检查)
// 但失败时重定向到首页,而非返回 JSON
// 成功时向 context 注入 uid/email/username/role
func AdminAuth(cfg *config.Config, userRepo *repository.UserRepo) gin.HandlerFunc {
return func(c *gin.Context) {
tokenStr, err := c.Cookie(common.CookieName)
if err != nil {
log.Printf("[AdminAuth] NO_COOKIE path=%s → 302", c.Request.URL.Path)
c.Redirect(http.StatusFound, "/")
c.Abort()
return
}
claims, err := parseToken(tokenStr, cfg.JWT.Secret)
if err != nil {
log.Printf("[AdminAuth] TOKEN_PARSE_FAIL path=%s err=%v → 302", c.Request.URL.Path, err)
common.ClearAuthCookies(c, cfg)
c.Redirect(http.StatusFound, "/")
c.Abort()
return
}
uid := uint(claims["uid"].(float64))
tokenVer := int(claims["ver"].(float64))
// 即时吊销检查
currentVer, err := userRepo.FindTokenVersion(uid)
if err != nil || tokenVer != currentVer {
if tokenVer != currentVer {
log.Printf("[AdminAuth] REVOKED: uid=%d tokenVer=%d dbVer=%d → 302", uid, tokenVer, currentVer)
} else {
log.Printf("[AdminAuth] DB_ERR: uid=%d err=%v → 302", uid, err)
}
common.ClearAuthCookies(c, cfg)
c.Redirect(http.StatusFound, "/")
c.Abort()
return
}
log.Printf("[AdminAuth] OK: uid=%d role=%v path=%s", uid, claims["role"], c.Request.URL.Path)
c.Set("uid", uid)
c.Set("email", claims["email"])
c.Set("username", claims["username"])
c.Set("role", claims["role"])
c.Next()
}
}
// RequireMinRole 角色权限检查(用于 API 路由)
// 不足时返回 JSON 403
func RequireMinRole(minRole string) gin.HandlerFunc {
return func(c *gin.Context) {
role, exists := c.Get("role")
if !exists || !model.HasMinRole(role.(string), minRole) {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
"success": false, "message": "权限不足",
})
return
}
c.Next()
}
}
// RequirePageRole 角色权限检查(用于 SSR 页面路由)
// 不足时 302 跳转首页
func RequirePageRole(minRole string) gin.HandlerFunc {
return func(c *gin.Context) {
role, exists := c.Get("role")
if !exists || !model.HasMinRole(role.(string), minRole) {
log.Printf("[RequirePageRole] DENY: role=%v need=%s path=%s → 302", role, minRole, c.Request.URL.Path)
c.Redirect(http.StatusFound, "/")
c.Abort()
return
}
c.Next()
}
}