package fwh_pro import ( "encoding/base64" "encoding/json" "fmt" "strings" "time" "go.uber.org/zap" ) var loginInfo LoginData = LoginData{ UserId: 0, Token: "", } type LoginPayload struct { LoginName string `json:"loginName"` Password string `json:"password"` Type int `json:"type"` Lang string `json:"lang"` } type LoginData struct { UserId uint `json:"userId"` Token string `json:"token"` } type LoginResponse struct { Code int `json:"code"` Msg string `json:"msg"` Data LoginData `json:"data"` Success bool `json:"success"` } type JwtPayload struct { AdminLevel int `json:"adminLevel"` LoginName string `json:"loginName"` AccountType int `json:"accountType"` GroupId int `json:"groupId"` Iss string `json:"iss"` UserManage int `json:"userManage"` Exp uint64 `json:"exp"` UserName string `json:"userName"` Iat uint64 `json:"iat"` UserId int `json:"userId"` } func Login() error { // 要发送的 JSON payload := LoginPayload{ LoginName: "FMU006", Password: "5583ae167cad1dbfb0b9f3d5312bebdf", Type: 1, Lang: "ZH_CN", } body, err := FwhHttpPostWithoutToken("https://oss.franklinwh.com/api-user/user/login", payload) if err != nil { return err } // logger.Std.Printf("Status: %s\nBody: %s", resp.Status, body) var loginRes LoginResponse // 反序列化(unmarshal) jsonErr := json.Unmarshal(body, &loginRes) if jsonErr != nil { return jsonErr } loginInfo.UserId = loginRes.Data.UserId loginInfo.Token = loginRes.Data.Token return nil } func isTokenExpired(token string) (bool, error) { parts := strings.Split(token, ".") if len(parts) != 3 { return false, fmt.Errorf("token 格式错误") } payloadSegment := parts[1] // JWT 使用 base64 URL encoding payloadBytes, err := base64.RawURLEncoding.DecodeString(payloadSegment) if err != nil { return false, err } var payload map[string]interface{} if err := json.Unmarshal(payloadBytes, &payload); err != nil { zap.L().Error("token payload解析失败", zap.String("payload", string(payloadBytes))) return false, err } expFloat, ok := payload["exp"].(float64) if !ok { return false, fmt.Errorf("token payload 中没有 exp") } expTime := time.Unix(int64(expFloat), 0) return time.Now().After(expTime), nil } func getLoginToken() string { // 判断是否已经有token if loginInfo.Token != "" { // 判断token是否过期 // token.payload加密,无法判断过期,改为判断401 // expired, err := isTokenExpired(loginInfo.Token) // if err != nil { // zap.L().Error("loginInfo.Token 解析出错.", zap.String("token", loginInfo.Token), zap.String("err", err.Error())) // return "" // } // if expired { // zap.L().Info("fwh Token 已过期") // } else { // Token 有效 return loginInfo.Token // } } // 重新登录 Login() return loginInfo.Token } func getUserId(token string) (int, error) { // JWT 由三部分组成: header.payload.signature parts := strings.Split(token, ".") if len(parts) < 2 { return 0, fmt.Errorf("getUserId: invalid token") } // 解码 payload 部分 payload, err := base64.RawURLEncoding.DecodeString(parts[1]) if err != nil { return 0, fmt.Errorf("getUserId: %s", err.Error()) } // 解析 JSON var claims JwtPayload if err := json.Unmarshal(payload, &claims); err != nil { return 0, fmt.Errorf("getUserId: %s", err.Error()) } return claims.UserId, nil } // 清空token func ClearToken() { loginInfo.UserId = 0 loginInfo.Token = "" } // 过期重新登录 - 提供给httpClient func reLogin() string { // 重新登录 Login() return loginInfo.Token }