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
- Recompute signature exactly as md5(appkey + sk + timestamp) using UTF-8 bytes and lowercase 32-char hex output, matching ApiAuthFilter.md5.
- Verify the sk in open_api_auth matches the client's secret; re-issue if rotated.
- Ensure the timestamp string used in signing is byte-identical to the one sent in the request.
- 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
- Use exact order appkey+sk+timestamp with no delimiters and UTF-8 bytes.
- Match the lowercase 32-char hex output of ApiAuthFilter.md5.
- Rotate sk on both sides together; never cache signed payloads across rotations.
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.