2026-07-03 15:58:29 +08:00
|
|
|
package middleware
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
"seeyon-filesystem/repository"
|
|
|
|
|
"seeyon-filesystem/utils"
|
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// JWTAuth JWT认证中间件
|
2026-07-10 17:33:33 +08:00
|
|
|
// 从请求头 token 中提取并验证JWT
|
2026-07-03 15:58:29 +08:00
|
|
|
// 验证通过后将用户信息存入上下文
|
|
|
|
|
func JWTAuth(secret string) gin.HandlerFunc {
|
|
|
|
|
return func(c *gin.Context) {
|
2026-07-10 17:33:33 +08:00
|
|
|
token := c.GetHeader("token")
|
|
|
|
|
if token == "" {
|
|
|
|
|
// 兼容查询参数 ?token=xxx (用于浏览器直接访问预览/下载链接)
|
|
|
|
|
token = c.Query("token")
|
2026-07-03 15:58:29 +08:00
|
|
|
}
|
2026-07-10 17:33:33 +08:00
|
|
|
if token == "" {
|
|
|
|
|
// 兼容 Authorization: Bearer xxx
|
|
|
|
|
authHeader := c.GetHeader("Authorization")
|
|
|
|
|
if authHeader != "" {
|
|
|
|
|
parts := strings.SplitN(authHeader, " ", 2)
|
|
|
|
|
if len(parts) == 2 && parts[0] == "Bearer" {
|
|
|
|
|
token = parts[1]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if token == "" {
|
|
|
|
|
utils.Unauthorized(c, "缺少token请求头")
|
2026-07-03 15:58:29 +08:00
|
|
|
c.Abort()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-10 17:33:33 +08:00
|
|
|
claims, err := utils.ParseToken(token, secret)
|
2026-07-03 15:58:29 +08:00
|
|
|
if err != nil {
|
|
|
|
|
utils.Unauthorized(c, "Token无效或已过期: "+err.Error())
|
|
|
|
|
c.Abort()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.Set("user_id", claims.UserID)
|
|
|
|
|
c.Set("username", claims.Username)
|
|
|
|
|
c.Set("role", claims.Role)
|
|
|
|
|
|
|
|
|
|
c.Next()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AdminAuth 管理员权限中间件
|
|
|
|
|
// 检查用户是否具有admin角色(兼容旧的Role字段)
|
|
|
|
|
func AdminAuth() gin.HandlerFunc {
|
|
|
|
|
return func(c *gin.Context) {
|
|
|
|
|
role, exists := c.Get("role")
|
|
|
|
|
if !exists || role.(string) != "admin" {
|
|
|
|
|
utils.Forbidden(c, "需要管理员权限")
|
|
|
|
|
c.Abort()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
c.Next()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RequirePermission 权限检查中间件
|
|
|
|
|
// 基于RBAC模型, 检查用户是否拥有指定权限
|
|
|
|
|
// 用法: middleware.RequirePermission("file:upload")
|
|
|
|
|
func RequirePermission(permissionCode string) gin.HandlerFunc {
|
|
|
|
|
return func(c *gin.Context) {
|
|
|
|
|
userID := GetCurrentUserID(c)
|
|
|
|
|
if userID == 0 {
|
|
|
|
|
utils.Unauthorized(c, "未登录")
|
|
|
|
|
c.Abort()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 管理员拥有所有权限
|
|
|
|
|
role, _ := c.Get("role")
|
|
|
|
|
if role == "admin" {
|
|
|
|
|
c.Next()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 通过RBAC查询权限
|
|
|
|
|
permRepo := repository.NewPermissionRepository()
|
|
|
|
|
codes, err := permRepo.GetUserPermissionCodes(userID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
utils.ServerError(c, "权限检查失败")
|
|
|
|
|
c.Abort()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, code := range codes {
|
|
|
|
|
if code == permissionCode || code == "*" {
|
|
|
|
|
c.Next()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
utils.Forbidden(c, "缺少权限: "+permissionCode)
|
|
|
|
|
c.Abort()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RequireAnyPermission 权限检查中间件(满足任一即可)
|
|
|
|
|
// 用法: middleware.RequireAnyPermission("file:upload", "file:manage")
|
|
|
|
|
func RequireAnyPermission(permissionCodes ...string) gin.HandlerFunc {
|
|
|
|
|
return func(c *gin.Context) {
|
|
|
|
|
userID := GetCurrentUserID(c)
|
|
|
|
|
if userID == 0 {
|
|
|
|
|
utils.Unauthorized(c, "未登录")
|
|
|
|
|
c.Abort()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
role, _ := c.Get("role")
|
|
|
|
|
if role == "admin" {
|
|
|
|
|
c.Next()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
permRepo := repository.NewPermissionRepository()
|
|
|
|
|
codes, err := permRepo.GetUserPermissionCodes(userID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
utils.ServerError(c, "权限检查失败")
|
|
|
|
|
c.Abort()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
codeSet := make(map[string]bool, len(codes))
|
|
|
|
|
for _, code := range codes {
|
|
|
|
|
codeSet[code] = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, required := range permissionCodes {
|
|
|
|
|
if codeSet[required] || codeSet["*"] {
|
|
|
|
|
c.Next()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
utils.Forbidden(c, "权限不足")
|
|
|
|
|
c.Abort()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetCurrentUserID 从上下文获取当前用户ID
|
|
|
|
|
func GetCurrentUserID(c *gin.Context) uint64 {
|
|
|
|
|
userID, exists := c.Get("user_id")
|
|
|
|
|
if !exists {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
return userID.(uint64)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetCurrentUsername 从上下文获取当前用户名
|
|
|
|
|
func GetCurrentUsername(c *gin.Context) string {
|
|
|
|
|
username, exists := c.Get("username")
|
|
|
|
|
if !exists {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return username.(string)
|
|
|
|
|
}
|