{"record":{"id":"df15f37941878ca2","repo":"jeecgboot/JeecgBoot","slug":"signature-df15f3","errorCode":null,"errorMessage":"signature签名已过期(超过五分钟)","messagePattern":"signature签名已过期\\(超过五分钟\\)","errorType":"exception","errorClass":"JeecgBootException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/filter/ApiAuthFilter.java","lineNumber":208,"sourceCode":"     * @param signature\n     * @param timestamp\n     * @return\n     */\n    protected void checkSignValid(String appkey, String signature, String timestamp) {\n        if (!StringUtils.hasText(appkey)) {\n            throw new JeecgBootException(\"appkey为空\");\n        }\n        if (!StringUtils.hasText(signature)) {\n            throw new JeecgBootException(\"signature为空\");\n        }\n        if (!StringUtils.hasText(timestamp)) {\n            throw new JeecgBootException(\"timastamp时间戳为空\");\n        }\n        if (!timestamp.matches(\"[0-9]*\")) {\n            throw new JeecgBootException(\"timastamp时间戳不合法\");\n        }\n        if (System.currentTimeMillis() - Long.parseLong(timestamp) > 5 * 60 * 1000) {\n            throw new JeecgBootException(\"signature签名已过期(超过五分钟)\");\n        }\n    }\n\n    /**\n     * 认证信息核验\n     * @param appKey\n     * @param signature\n     * @param timestamp\n     * @param openApiAuth\n     * @return\n     * @throws Exception\n     */\n    protected void checkSignature(String appKey, String signature, String timestamp, OpenApiAuth openApiAuth) {\n        if(openApiAuth==null){\n            throw new JeecgBootException(\"不存在认证信息\");\n        }\n\n        if(!appKey.equals(openApiAuth.getAk())){","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/filter/ApiAuthFilter.java#L190-L226","documentation":"Thrown by checkSignValid when System.currentTimeMillis() minus the supplied timestamp exceeds 5*60*1000 ms (5 minutes). This is a replay-protection window: a captured signature cannot be reused after 5 minutes. There is no negative/future check, so clocks ahead are tolerated; only an old timestamp triggers this.","triggerScenarios":"Client clock is more than 5 minutes behind the server; the request was replayed/queued > 5 min after signing; container clock skew between client pod and server pod.","commonSituations":"NTP drift on client or server; long network/CPU delays before the filter processes the request; clients caching pre-signed requests.","solutions":["Synchronize client and server clocks via NTP/chrony; keep drift under 1 minute.","Generate the timestamp immediately before each request rather than caching signed URLs.","If the legitimate deployment has known skew, the 5-minute constant must be widened in code (no config property exists)."],"exampleFix":"// before: long ts = cachedTimestamp;  // generated minutes ago\n// after:  long ts = System.currentTimeMillis();  // fresh per request\n//         String sig = md5(ak + sk + ts);","handlingStrategy":"validation","validationCode":"// Sign as late as possible and assert freshness before sending\nString ts = String.valueOf(System.currentTimeMillis());\nString sig = md5(appkey + sk + ts);\nlong skew = Math.abs(System.currentTimeMillis() - Long.parseLong(ts));\nif (skew > 60_000L) { /* resync clock / regenerate */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run NTP/chrony on both client and server; keep skew under 1 minute.","Generate timestamp and signature immediately before each request; never cache.","If known legitimate skew exists, widen the 5-minute constant in code (no config property exists)."],"tags":["openapi","auth","signature","replay-protection","clock-skew"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}