{"record":{"id":"5ddac080ec0bb383","repo":"jeecgboot/JeecgBoot","slug":"appkey-5ddac0","errorCode":null,"errorMessage":"该appKey未授权当前接口","messagePattern":"该appKey未授权当前接口","errorType":"exception","errorClass":"JeecgBootException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/filter/ApiAuthFilter.java","lineNumber":247,"sourceCode":"\n        if (!signature.equals(md5(appKey + openApiAuth.getSk() + timestamp))) {\n            throw new JeecgBootException(\"signature签名错误\");\n        }\n    }\n\n    protected void checkPermission(OpenApi openApi, OpenApiAuth openApiAuth) {\n        List<OpenApiPermission> permissionList = openApiPermissionService.findByAuthId(openApiAuth.getId());\n\n        boolean hasPermission = false;\n        for (OpenApiPermission permission : permissionList) {\n            if (permission.getApiId().equals(openApi.getId())) {\n                hasPermission = true;\n                break;\n            }\n        }\n\n        if (!hasPermission) {\n            throw new JeecgBootException(\"该appKey未授权当前接口\");\n        }\n    }\n\n    /**\n     * @return String    返回类型\n     * @Title: MD5\n     * @Description: 【MD5加密】\n     */\n    protected static String md5(String sourceStr) {\n        String result = \"\";\n        try {\n            MessageDigest md = MessageDigest.getInstance(\"MD5\");\n            md.update(sourceStr.getBytes(\"utf-8\"));\n            byte[] hash = md.digest();\n            int i;\n            StringBuffer buf = new StringBuffer(32);\n            for (int offset = 0; offset < hash.length; offset++) {\n                i = hash[offset];","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/filter/ApiAuthFilter.java#L229-L265","documentation":"Thrown by checkPermission when none of the OpenApiPermission rows linked to the auth account (openApiAuth.id) reference the requested API (openApi.id). After signature validation passes, this enforces per-API authorization: the appkey must be explicitly granted the specific interface it is calling.","triggerScenarios":"The caller authenticated correctly but the OpenApiAuth account has no OpenApiPermission row for this API; the permission row was revoked; the api_id on the permission row does not match the openApi row being called.","commonSituations":"New partner given credentials but not granted the specific API; permission revoked during an audit but client still calling; API was re-created with a new id and old permissions dangle.","solutions":["In the admin UI, add an OpenApiPermission entry linking the auth account to the requested OpenApi record.","Verify the api_id on the permission row matches openApi.getId() exactly.","Confirm the permission row is not soft-deleted or filtered out by findByAuthId."],"exampleFix":"// before: open_api_permission has no row for (auth_id=A, api_id=42)\n// after:  INSERT INTO open_api_permission(auth_id, api_id) VALUES ('A','42');","handlingStrategy":"validation","validationCode":"// Verify permission exists before exposing the API to the caller (admin side)\nboolean granted = openApiPermissionService.findByAuthId(authId).stream()\n    .anyMatch(p -> p.getApiId().equals(apiId));\nif (!granted) { /* grant via admin before the call */ }","typeGuard":null,"tryCatchPattern":"try {\n    openApi.call(...);\n} catch (JeecgBootException e) {\n    if (e.getMessage().contains(\"未授权当前接口\")) {\n        // request permission grant; do not retry until granted\n    }\n}","preventionTips":["Grant per-API permission explicitly when provisioning an account.","When re-creating an OpenApi record, migrate its api_id onto existing permission rows.","Audit for orphaned/soft-deleted permission rows periodically."],"tags":["openapi","auth","authorization","permissions"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}