jeecgboot/JeecgBoot · error · IllegalArgumentException

Sign签名校验失败:{message}

Error message

Sign签名校验失败:{message}

What it means

This is a catch-all wrapper for any unexpected exception during signature validation that is not an IllegalArgumentException. It concatenates 'Sign签名校验失败:' with the original exception message. This fires when the validation logic encounters an IOException (failed BodyReaderHttpServletRequestWrapper body re-read), a NumberFormatException (invalid X-TIMESTAMP value), or any other runtime exception.

Source

Thrown at jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/interceptor/SignAuthInterceptor.java:132

                }
            }

            //2.校验签名
            boolean isSigned = SignUtil.verifySign(allParams,headerSign);

            if (isSigned) {
                log.debug("签名验证通过");
            } else {
                log.error("签名验证失败, 参数: {}", allParams);
                throw new IllegalArgumentException("Sign签名校验失败!");
            }
        } catch (IllegalArgumentException e) {
            // 重新抛出签名验证异常
            throw e;
        } catch (Exception e) {
            // 包装其他异常(如IOException)
            log.error("签名验证异常: {}", e.getMessage());
            throw new IllegalArgumentException("Sign签名校验失败:" + e.getMessage());
        }
    }

}

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Ensure X-TIMESTAMP is a valid numeric string (either 14-digit yyyyMMddHHmmss or 13-digit Unix ms).
  2. Verify no upstream filter consumes the request body without wrapping it in a BodyReaderHttpServletRequestWrapper.
  3. Check server logs for the specific wrapped exception message (the getMessage() portion after the colon) to identify the root cause.
  4. If the error is from SpringContextUtils, verify the JeecgBaseConfig bean is properly configured and loaded.

Example fix

// before (client) — X-TIMESTAMP is a date string
conn.setRequestProperty("X-TIMESTAMP", "2024-01-01 12:00:00");

// after — X-TIMESTAMP is a valid numeric value
conn.setRequestProperty("X-TIMESTAMP", String.valueOf(System.currentTimeMillis()));
Defensive patterns

Strategy: try-catch

Validate before calling

// Client-side: validate timestamp format before sending
String xTimestamp = String.valueOf(System.currentTimeMillis());
try {
    Long.parseLong(xTimestamp); // verify it's a valid number
} catch (NumberFormatException e) {
    throw new IllegalStateException("Invalid timestamp format");
}

Type guard

public static boolean isValidTimestampFormat(String xTimestamp) {
    if (xTimestamp == null || xTimestamp.isEmpty()) return false;
    try {
        Long.parseLong(xTimestamp);
        return xTimestamp.length() == 14 || xTimestamp.length() == 13;
    } catch (NumberFormatException e) {
        return false;
    }
}

Try / catch

try {
    response = httpClient.execute(request);
} catch (IllegalArgumentException e) {
    String msg = e.getMessage();
    if (msg.startsWith("Sign签名校验失败:")) {
        // Extract the underlying cause from the message suffix
        String cause = msg.substring(msg.indexOf(':') + 1);
        log.error("Signature validation infrastructure error: {}", cause);
    }
    throw e;
}

Prevention

When it happens

Trigger: X-TIMESTAMP contains a non-numeric value causing NumberFormatException at Long.parseLong (line 89). The request body has already been consumed by another filter, causing BodyReaderHttpServletRequestWrapper to fail. HttpUtils.getAllParams throws an IOException while reading the body. SpringContextUtils.getBean(JeecgBaseConfig.class) fails during SignUtil.getSignatureSecret().

Common situations: Client sends X-TIMESTAMP=NaN or a date string instead of a number. A filter upstream consumed the InputStream without wrapping it. The application context is not fully initialized when the interceptor fires. A malformed multipart request body.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/f03cd370484a067b. Report an issue: GitHub.