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.

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)

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.