{"record":{"id":"061b6721f983c820","repo":"flipped-aurora/gin-vue-admin","slug":"token-061b67","errorCode":null,"errorMessage":"token尚未激活","messagePattern":"token尚未激活","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/utils/jwt.go","lineNumber":20,"sourceCode":"\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"time\"\n\n\t\"github.com/flipped-aurora/gin-vue-admin/server/global\"\n\t\"github.com/flipped-aurora/gin-vue-admin/server/model/system/request\"\n\tjwt \"github.com/golang-jwt/jwt/v5\"\n)\n\ntype JWT struct {\n\tSigningKey []byte\n}\n\nvar (\n\tTokenValid            = errors.New(\"未知错误\")\n\tTokenExpired          = errors.New(\"token已过期\")\n\tTokenNotValidYet      = errors.New(\"token尚未激活\")\n\tTokenMalformed        = errors.New(\"这不是一个token\")\n\tTokenSignatureInvalid = errors.New(\"无效签名\")\n\tTokenInvalid          = errors.New(\"无法处理此token\")\n)\n\nfunc NewJWT() *JWT {\n\treturn &JWT{\n\t\t[]byte(global.GVA_CONFIG.JWT.SigningKey),\n\t}\n}\n\nfunc (j *JWT) CreateClaims(baseClaims request.BaseClaims) request.CustomClaims {\n\tbf, _ := ParseDuration(global.GVA_CONFIG.JWT.BufferTime)\n\tep, _ := ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)\n\tclaims := request.CustomClaims{\n\t\tBaseClaims: baseClaims,\n\t\tBufferTime: int64(bf / time.Second), // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失\n\t\tRegisteredClaims: jwt.RegisteredClaims{","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/utils/jwt.go#L2-L38","documentation":"TokenNotValidYet is returned by ParseToken when the token's nbf (not-before) claim is later than the current time. The token is structurally valid but is being used before its activation window opens.","triggerScenarios":"A token issued with a future nbf/iat is presented immediately; server clock is behind the issuing server's clock, so a token issued 'now' by machine A looks not-yet-valid on machine B.","commonSituations":"Clock skew between issuing and validating servers or between a token minted on a machine with a fast clock; pre-issued tokens with an intentional future nbf used too early; containers with wrong timezone/UTC offsets.","solutions":["Sync clocks on both issuing and validating machines (chrony/NTP).","Re-issue a token without a future nbf if immediate use is intended.","If pre-issued (future-nbf) tokens are intentional, delay client use until after nbf."],"exampleFix":"// before\njwtClaims := ... // token minted with future nbf on skewed host\nclaims, err := utils.ParseToken(token) // token尚未激活\n// after\n// ntpdate / chronyc makestep  -> clocks aligned\n// re-issue token with nbf <= now\nclaims, err := utils.ParseToken(token) // ok","handlingStrategy":"try-catch","validationCode":"if payload[\"nbf\"] && payload[\"nbf\"]*1000 > Date.now() {\n    return errors.New(\"token not active yet; check clocks or issue time\")\n}","typeGuard":null,"tryCatchPattern":"claims, err := utils.ParseToken(token)\nif errors.Is(err, utils.TokenNotValidYet) {\n    // clock skew likely: alert ops to sync NTP; do not accept the token early\n    return nil, ErrTokenNotActive\n}","preventionTips":["Run NTP/chrony on all servers that mint or validate JWTs","Do not set a future nbf unless delayed activation is intentional","Keep issuing and validating services in the same timezone/UTC convention"],"tags":["jwt","auth","go","clock-skew"],"backgroundTag":"jwt-token-not-valid-yet","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}