jeecgboot/JeecgBoot · error · JeecgBootException

signature签名错误

Error message

signature签名错误

What it means

Thrown by checkSignature when the supplied signature does not equal md5(appKey + openApiAuth.getSk() + timestamp). The MD5 is computed over the concatenation of appkey, the stored secret key (sk), and the timestamp - in that exact order, no delimiters. Any mismatch in value, order, encoding, or the sk itself produces this error.

Source

Thrown at jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/filter/ApiAuthFilter.java:231

     * 认证信息核验
     * @param appKey
     * @param signature
     * @param timestamp
     * @param openApiAuth
     * @return
     * @throws Exception
     */
    protected void checkSignature(String appKey, String signature, String timestamp, OpenApiAuth openApiAuth) {
        if(openApiAuth==null){
            throw new JeecgBootException("不存在认证信息");
        }

        if(!appKey.equals(openApiAuth.getAk())){
            throw new JeecgBootException("appkey错误");
        }

        if (!signature.equals(md5(appKey + openApiAuth.getSk() + timestamp))) {
            throw new JeecgBootException("signature签名错误");
        }
    }

    protected void checkPermission(OpenApi openApi, OpenApiAuth openApiAuth) {
        List<OpenApiPermission> permissionList = openApiPermissionService.findByAuthId(openApiAuth.getId());

        boolean hasPermission = false;
        for (OpenApiPermission permission : permissionList) {
            if (permission.getApiId().equals(openApi.getId())) {
                hasPermission = true;
                break;
            }
        }

        if (!hasPermission) {
            throw new JeecgBootException("该appKey未授权当前接口");
        }
    }

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Recompute signature exactly as md5(appkey + sk + timestamp) using UTF-8 bytes and lowercase 32-char hex output, matching ApiAuthFilter.md5.
  2. Verify the sk in open_api_auth matches the client's secret; re-issue if rotated.
  3. Ensure the timestamp string used in signing is byte-identical to the one sent in the request.
  4. Confirm there are no hidden delimiters or trailing characters in any of the three inputs.

Example fix

// before: signature = md5(sk + appkey + ts)  // wrong order
// after:  signature = md5(appkey + sk + ts)   // matches server:
//         MessageDigest.getInstance("MD5"), UTF-8, lowercase 32-hex
Defensive patterns

Strategy: validation

Validate before calling

// Reproduce the server's exact signature locally and compare before sending
String expected = md5LowerHex(appkey + sk + timestamp); // UTF-8, 32-char lowercase hex
if (!expected.equals(signature)) {
    throw new IllegalStateException("signature mismatch before send");
}
// md5LowerHex must match ApiAuthFilter.md5 byte-for-byte

Try / catch

try {
    openApi.call(...);
} catch (JeecgBootException e) {
    if (e.getMessage().contains("signature签名错误")) {
        // do NOT retry with same signature; recompute with current sk + ts and resend once
    }
}

Prevention

When it happens

Trigger: Client uses the wrong sk, wrong concatenation order, wrong encoding (non-UTF-8), a different timestamp than the one sent, or computes a different hash algorithm (e.g. SHA-256); the stored sk was rotated and the client has the old value.

Common situations: Secret rotation not propagated to the client; client builds signature with a different field order; the md5 helper in the codebase (ApiAuthFilter.md5) lowercases hex while the client uppercases; locale-dependent byte encoding.

Related errors


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