package utils import ( "context" "net" "time" "kra/pkg/jwt" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/redis/go-redis/v9" "go.uber.org/zap" ) // 全局 JWT 实例(需要在初始化时设置) var jwtInstance *jwt.JWT // 全局日志实例(需要在初始化时设置) var logger *zap.Logger // 全局 Redis 客户端(需要在初始化时设置) var redisClient redis.UniversalClient // JWT 过期时间 var jwtExpiresTime time.Duration = 7 * 24 * time.Hour // SetJWT 设置全局 JWT 实例 func SetJWT(j *jwt.JWT) { jwtInstance = j } // SetLogger 设置全局日志实例 func SetLogger(l *zap.Logger) { logger = l } // SetRedisClient 设置全局 Redis 客户端 func SetRedisClient(client redis.UniversalClient) { redisClient = client } // SetJWTExpiresTime 设置 JWT 过期时间 func SetJWTExpiresTime(d time.Duration) { jwtExpiresTime = d } // SetRedisJWT 设置 Redis JWT func SetRedisJWT(token, username string) error { if redisClient == nil { return nil } return redisClient.Set(context.Background(), "jwt:"+username, token, jwtExpiresTime).Err() } // GetRedisJWT 从 Redis 获取 JWT func GetRedisJWT(username string) (string, error) { if redisClient == nil { return "", redis.Nil } return redisClient.Get(context.Background(), "jwt:"+username).Result() } // ClearToken 清除 token func ClearToken(c *gin.Context) { // 增加cookie x-token 向来源的web添加 host, _, err := net.SplitHostPort(c.Request.Host) if err != nil { host = c.Request.Host } if net.ParseIP(host) != nil { c.SetCookie("x-token", "", -1, "/", "", false, false) } else { c.SetCookie("x-token", "", -1, "/", host, false, false) } } // SetToken 设置 token 到 cookie func SetToken(c *gin.Context, token string, maxAge int) { // 增加cookie x-token 向来源的web添加 host, _, err := net.SplitHostPort(c.Request.Host) if err != nil { host = c.Request.Host } if net.ParseIP(host) != nil { c.SetCookie("x-token", token, maxAge, "/", "", false, false) } else { c.SetCookie("x-token", token, maxAge, "/", host, false, false) } } // GetToken 从请求中获取 token func GetToken(c *gin.Context) string { token := c.Request.Header.Get("x-token") if token == "" { token, _ = c.Cookie("x-token") if token != "" && jwtInstance != nil { claims, err := jwtInstance.ParseToken(token) if err != nil { if logger != nil { logger.Error("重新写入cookie token失败,未能成功解析token,请检查请求头是否存在x-token且claims是否为规定结构") } return token } SetToken(c, token, int(claims.ExpiresAt.Unix()-time.Now().Unix())) } } return token } // GetClaims 从 context 获取 claims func GetClaims(c *gin.Context) (*jwt.CustomClaims, error) { token := GetToken(c) if jwtInstance == nil { return nil, jwt.ErrTokenInvalid } claims, err := jwtInstance.ParseToken(token) if err != nil { if logger != nil { logger.Error("从Gin的Context中获取从jwt解析信息失败, 请检查请求头是否存在x-token且claims是否为规定结构") } } return claims, err } // GetUserID 从 Gin 的 Context 中获取从 jwt 解析出来的用户 ID func GetUserID(c *gin.Context) uint { if claims, exists := c.Get("claims"); !exists { if cl, err := GetClaims(c); err != nil { return 0 } else { return cl.BaseClaims.ID } } else { waitUse := claims.(*jwt.CustomClaims) return waitUse.BaseClaims.ID } } // GetUserUuid 从 Gin 的 Context 中获取从 jwt 解析出来的用户 UUID func GetUserUuid(c *gin.Context) uuid.UUID { if claims, exists := c.Get("claims"); !exists { if cl, err := GetClaims(c); err != nil { return uuid.UUID{} } else { uid, _ := uuid.Parse(cl.BaseClaims.UUID) return uid } } else { waitUse := claims.(*jwt.CustomClaims) uid, _ := uuid.Parse(waitUse.BaseClaims.UUID) return uid } } // GetUserAuthorityId 从 Gin 的 Context 中获取从 jwt 解析出来的用户角色 id func GetUserAuthorityId(c *gin.Context) uint { if claims, exists := c.Get("claims"); !exists { if cl, err := GetClaims(c); err != nil { return 0 } else { return cl.BaseClaims.AuthorityID } } else { waitUse := claims.(*jwt.CustomClaims) return waitUse.BaseClaims.AuthorityID } } // GetUserInfo 从 Gin 的 Context 中获取从 jwt 解析出来的用户信息 func GetUserInfo(c *gin.Context) *jwt.CustomClaims { if claims, exists := c.Get("claims"); !exists { if cl, err := GetClaims(c); err != nil { return nil } else { return cl } } else { waitUse := claims.(*jwt.CustomClaims) return waitUse } } // GetUserName 从 Gin 的 Context 中获取从 jwt 解析出来的用户名 func GetUserName(c *gin.Context) string { if claims, exists := c.Get("claims"); !exists { if cl, err := GetClaims(c); err != nil { return "" } else { return cl.Username } } else { waitUse := claims.(*jwt.CustomClaims) return waitUse.Username } }