110 lines
2.5 KiB
Go
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"
|
|
}
|