Files
filestoragesystem/go/internal/middleware/auth.go
T
2026-08-23 00:48:10 +08:00

110 lines
2.5 KiB
Go

package middleware
import (
"strings"
"github.com/gin-gonic/gin"
"filestoragesystem/internal/model"
"filestoragesystem/internal/service"
"filestoragesystem/internal/utils"
"filestoragesystem/pkg/apperr"
)
// 上下文键
const (
CtxUser = "authUser" // *model.User
CtxUserID = "authUserID" // uint
CtxUsername = "authUsername" // string
CtxRoleCode = "authRoleCode" // string
CtxPermissions = "authPermissions" // map[string]bool
)
// Auth 认证中间件:支持 JWT Bearer 与 API Key HMAC-SHA256签名两种方式
func Auth(authSvc *service.AuthService) gin.HandlerFunc {
return func(c *gin.Context) {
var user *model.User
// 1. JWT Bearer Token
header := c.GetHeader("Authorization")
if strings.HasPrefix(header, "Bearer ") {
claims, err := utils.ParseToken(strings.TrimPrefix(header, "Bearer "))
if err != nil {
utils.Unauthorized(c, "Token无效或已过期")
return
}
u, err := authSvc.LoadUserByID(claims.UserID)
if err != nil {
utils.Unauthorized(c, apperr.ErrUnauthorized.Error())
return
}
user = u
} else if ak := c.GetHeader("X-Access-Key"); ak != "" {
// 2. API Key + Secret HMAC-SHA256签名
u, err := authSvc.VerifyAPIKeySignature(
ak,
c.GetHeader("X-Timestamp"),
c.GetHeader("X-Nonce"),
c.GetHeader("X-Signature"),
c.Request.Method,
c.Request.URL.Path,
)
if err != nil {
utils.Unauthorized(c, err.Error())
return
}
user = u
} else {
utils.Unauthorized(c, "缺少认证信息")
return
}
if user == nil {
utils.Unauthorized(c, apperr.ErrUnauthorized.Error())
return
}
c.Set(CtxUser, user)
c.Set(CtxUserID, user.ID)
c.Set(CtxUsername, user.Username)
roleCode := ""
if user.Role != nil {
roleCode = user.Role.Code
}
c.Set(CtxRoleCode, roleCode)
c.Set(CtxPermissions, service.PermissionCodesOf(user))
c.Next()
}
}
// CurrentUser 从上下文获取当前用户
func CurrentUser(c *gin.Context) *model.User {
if v, ok := c.Get(CtxUser); ok {
if u, ok := v.(*model.User); ok {
return u
}
}
return nil
}
// CurrentUserID 当前用户ID
func CurrentUserID(c *gin.Context) uint {
if v, ok := c.Get(CtxUserID); ok {
if id, ok := v.(uint); ok {
return id
}
}
return 0
}
// IsSuperAdmin 是否超级管理员
func IsSuperAdmin(c *gin.Context) bool {
return c.GetString(CtxRoleCode) == "super_admin"
}
// IsAdmin 是否管理员(super_admin或admin)
func IsAdmin(c *gin.Context) bool {
rc := c.GetString(CtxRoleCode)
return rc == "super_admin" || rc == "admin"
}