package token import ( "encoding/json" "fmt" "time" "ems.agt/src/framework/config" cachekeyConstants "ems.agt/src/framework/constants/cachekey" tokenConstants "ems.agt/src/framework/constants/token" "ems.agt/src/framework/logger" redisCahe "ems.agt/src/framework/redis" "ems.agt/src/framework/utils/generate" "ems.agt/src/framework/vo" jwt "github.com/golang-jwt/jwt/v5" ) // Remove 清除登录用户信息UUID func Remove(tokenStr string) string { claims, err := Verify(tokenStr) if err != nil { logger.Errorf("token verify err %v", err) return "" } // 清除缓存KEY uuid := claims[tokenConstants.JWT_UUID].(string) tokenKey := cachekeyConstants.LOGIN_TOKEN_KEY + uuid hasKey, _ := redisCahe.Has("", tokenKey) if hasKey { redisCahe.Del("", tokenKey) } return claims[tokenConstants.JWT_NAME].(string) } // Create 令牌生成 func Create(loginUser *vo.LoginUser, ilobArgs ...string) string { // 生成用户唯一tokne16位 loginUser.UUID = generate.Code(16) // 设置请求用户登录客户端 loginUser.IPAddr = ilobArgs[0] loginUser.LoginLocation = ilobArgs[1] loginUser.OS = ilobArgs[2] loginUser.Browser = ilobArgs[3] // 设置用户令牌有效期并存入缓存 Cache(loginUser) // 设置登录IP和登录时间 loginUser.User.LoginIP = loginUser.IPAddr loginUser.User.LoginDate = loginUser.LoginTime // 令牌算法 HS256 HS384 HS512 algorithm := config.Get("jwt.algorithm").(string) var method *jwt.SigningMethodHMAC switch algorithm { case "HS512": method = jwt.SigningMethodHS512 case "HS384": method = jwt.SigningMethodHS384 case "HS256": default: method = jwt.SigningMethodHS256 } // 生成令牌负荷绑定uuid标识 jwtToken := jwt.NewWithClaims(method, jwt.MapClaims{ tokenConstants.JWT_UUID: loginUser.UUID, tokenConstants.JWT_KEY: loginUser.UserID, tokenConstants.JWT_NAME: loginUser.User.UserName, "exp": loginUser.ExpireTime, "ait": loginUser.LoginTime, }) // 生成令牌设置密钥 secret := config.Get("jwt.secret").(string) tokenStr, err := jwtToken.SignedString([]byte(secret)) if err != nil { logger.Infof("jwt sign err : %v", err) return "" } return tokenStr } // Cache 缓存登录用户信息 func Cache(loginUser *vo.LoginUser) { // 计算配置的有效期 expTime := config.Get("jwt.expiresIn").(int) expTimestamp := time.Duration(expTime) * time.Minute iatTimestamp := time.Now().UnixMilli() loginUser.LoginTime = iatTimestamp loginUser.ExpireTime = iatTimestamp + expTimestamp.Milliseconds() // 根据登录标识将loginUser缓存 tokenKey := cachekeyConstants.LOGIN_TOKEN_KEY + loginUser.UUID jsonBytes, err := json.Marshal(loginUser) if err != nil { return } redisCahe.SetByExpire("", tokenKey, string(jsonBytes), expTimestamp) } // RefreshIn 验证令牌有效期,相差不足xx分钟,自动刷新缓存 func RefreshIn(loginUser *vo.LoginUser) { // 相差不足xx分钟,自动刷新缓存 refreshTime := config.Get("jwt.refreshIn").(int) refreshTimestamp := time.Duration(refreshTime) * time.Minute // 过期时间 expireTimestamp := loginUser.ExpireTime currentTimestamp := time.Now().UnixMilli() if expireTimestamp-currentTimestamp <= refreshTimestamp.Milliseconds() { Cache(loginUser) } } // Verify 校验令牌是否有效 func Verify(tokenString string) (jwt.MapClaims, error) { token, err := jwt.Parse(tokenString, func(token *jwt.Token) (any, error) { // 判断加密算法是预期的加密算法 if _, ok := token.Method.(*jwt.SigningMethodHMAC); ok { secret := config.Get("jwt.secret").(string) return []byte(secret), nil } return nil, jwt.ErrSignatureInvalid }) if err != nil { logger.Errorf("token String Verify : %v", err) // 无效身份授权 return nil, fmt.Errorf("invalid identity authorization") } // 如果解析负荷成功并通过签名校验 if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { return claims, nil } return nil, fmt.Errorf("token valid error") } // LoginUser 缓存的登录用户信息 func LoginUser(claims jwt.MapClaims) vo.LoginUser { uuid := claims[tokenConstants.JWT_UUID].(string) tokenKey := cachekeyConstants.LOGIN_TOKEN_KEY + uuid hasKey, _ := redisCahe.Has("", tokenKey) var loginUser vo.LoginUser if hasKey { loginUserStr, _ := redisCahe.Get("", tokenKey) if loginUserStr == "" { return loginUser } err := json.Unmarshal([]byte(loginUserStr), &loginUser) if err != nil { logger.Errorf("loginuser info json err : %v", err) return loginUser } return loginUser } return loginUser }