jeecgboot/JeecgBoot · error · IllegalArgumentException

Sign签名校验失败!

Error message

Sign签名校验失败!

What it means

Thrown by SignatureCheckAspect when signAuthInterceptor.validateSignature() throws an IllegalArgumentException during signature validation, and the @SignatureCheck annotation's errorMessage() is set to the default 'Sign签名校验失败!'. In this case the original detailed error (from SignAuthInterceptor) is re-thrown as-is. If a custom errorMessage is configured, a new IllegalArgumentException with that custom message is thrown instead. This means the X-SIGN header is missing, the timestamp is expired, or the signature does not match the computed value.

Solutions

  1. Verify the signing secret key matches between client and server (jeecg.sign.secret configuration).
  2. Ensure the client sends both X-SIGN (computed signature) and X-TIMESTAMP headers.
  3. Check for clock skew — the server validates timestamp freshness; sync client and server clocks (NTP).
  4. Verify the signature algorithm matches — review SignAuthInterceptor.validateSignature() for the exact signing logic (parameter sorting, body inclusion, hash algorithm).
  5. Ensure no intermediary (gateway, proxy) modifies the request body or query parameters after signing.

Example fix

// Front-end: compute and send signature
const params = { id: 123, name: 'test', _t: Date.now() };
const signStr = Object.keys(params).sort().map(k => `${k}=${params[k]}`).join('&');
const sign = CryptoJS.HmacSHA256(signStr, SIGN_SECRET).toString();

axios.post('/api/signed-endpoint', body, {
    headers: {
        'X-SIGN': sign,
        'X-TIMESTAMP': params._t.toString()
    }
});
// Verify: server sign secret == client sign secret
// Verify: parameter sorting and concatenation order match server logic
Defensive patterns

Strategy: validation

Validate before calling

// Front-end: compute and verify signature before sending
const sortedParams = Object.keys(params).sort();
const signStr = sortedParams.map(k => `${k}=${params[k]}`).join('&');
const expectedSign = CryptoJS.HmacSHA256(signStr + timestamp, SIGN_SECRET).toString();
if (expectedSign !== computedSign) {
    console.error('Signature mismatch — do not send');
}

Try / catch

try {
    // call signed API endpoint
} catch (error) {
    if (error.response?.data?.message?.includes('签名校验失败')) {
        log.error('Signature validation failed — check signing key and algorithm');
    }
    throw error;
}

Prevention

When it happens

Trigger: API request to a @SignatureCheck-annotated endpoint without the X-SIGN header; X-SIGN value does not match the HMAC/signature computed from the request parameters; X-TIMESTAMP is missing or outside the allowed time window; request body was modified after signing; wrong signing key configured on client vs server.

Common situations: Client and server have different signing secret keys; client-side signature algorithm does not match server-side (SignAuthInterceptor); timestamp clock skew between client and server exceeds the allowed window; request body is modified by a proxy/gateway after signing; front-end omits the X-SIGN or X-TIMESTAMP header.

Related errors


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

Appendix: source

Thrown at jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/aspect/SignatureCheckAspect.java:103

        HttpServletRequest request = attributes.getRequest();
        log.info("X-SIGN: {}, X-TIMESTAMP: {}", request.getHeader("X-SIGN"), request.getHeader("X-TIMESTAMP"));
        
        try {
            // 直接调用SignAuthInterceptor的验证逻辑
            signAuthInterceptor.validateSignature(request, bodyParam);
            log.info("AOP签名验证通过");
            
        } catch (IllegalArgumentException e) {
            // 使用注解中配置的错误消息,或者保留原始错误消息
            String errorMessage = signatureCheck.errorMessage();
            log.error("AOP签名验证失败: {}", e.getMessage());
            
            if ("Sign签名校验失败!".equals(errorMessage)) {
                // 如果是默认错误消息,使用原始的详细错误信息
                throw e;
            } else {
                // 如果是自定义错误消息,使用自定义消息
                throw new IllegalArgumentException(errorMessage, e);
            }
        } catch (Exception e) {
            // 包装其他异常
            String errorMessage = signatureCheck.errorMessage();
            log.error("AOP签名验证异常: {}", e.getMessage());
            throw new IllegalArgumentException(errorMessage, e);
        }
    }
}

View on GitHub (pinned to 96fb33f5ec)