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" }