dromara/Sa-Token · error · ApiKeyException
12312
12312
Error message
该 API Key 不属于用户:
What it means
Thrown by SaApiKeyTemplate.checkApiKeyLoginId(String, Object) when the key exists but its loginId (stringified) does not equal the passed loginId. Code 12312 marks an ownership mismatch — the key is valid but belongs to a different account.
Source
Thrown at sa-token-plugin/sa-token-apikey/src/main/java/cn/dev33/satoken/apikey/template/SaApiKeyTemplate.java:384
return true;
} catch (ApiKeyException e) {
return false;
}
}
/**
* 校验:指定 ApiKey 是否属于指定 LoginId,如果不是则抛出异常
*
* @param apiKey /
* @param loginId /
*/
public void checkApiKeyLoginId(String apiKey, Object loginId) {
ApiKeyModel ak = getApiKey(apiKey);
if(ak == null) {
throw new ApiKeyException("无效 API Key: " + apiKey).setApiKey(apiKey).setCode(SaApiKeyErrorCode.CODE_12301);
}
if (SaFoxUtil.notEquals(String.valueOf(ak.getLoginId()), String.valueOf(loginId))) {
throw new ApiKeyException("该 API Key 不属于用户: " + loginId)
.setApiKey(apiKey)
.setCode(SaApiKeyErrorCode.CODE_12312);
}
}
// ------------------- 索引操作
/**
* 调整指定 SaSession 的 TTL 值,以保证最小化内存占用
* @param loginId /
* @param session 可填写 null,代表使用 loginId 现场查询
*/
public void adjustIndex(Object loginId, SaSession session) {
// 先判断是否开启索引
if(! getIsRecordIndex()) {
SaManager.getLog().warn("当前 API Key 模块未开启索引记录功能,无法执行 adjustIndex 操作");
return;View on GitHub (pinned to ac2c7f6e94)
Solutions
- Verify which loginId the key was issued to: saApiKeyTemplate.getApiKey(apiKey).getLoginId()
- Make the client use its own key (per-account issuance) instead of a shared one, or drop the ownership check if the key is intentionally shared
- Check for id formatting differences (leading zeros, numeric type vs string) between creation and check time
Example fix
// before // session user 10002, but key belongs to 10001 saApiKeyTemplate.checkApiKeyLoginId(apiKey, StpUtil.getLoginId()); // throws 12312 // after // issue per-user keys so ownership holds String key = saApiKeyTemplate.createApiKey(StpUtil.getLoginIdAsLong(), "self", 3600*24); saApiKeyTemplate.checkApiKeyLoginId(key, StpUtil.getLoginId());
Defensive patterns
Strategy: validation
Validate before calling
ApiKeyModel ak = saApiKeyTemplate.getApiKey(apiKey);
if (ak == null || !String.valueOf(ak.getLoginId()).equals(String.valueOf(currentLoginId))) {
return forbidden("key does not belong to current user");
} Try / catch
catch (ApiKeyException e) { if (e.getCode() == SaApiKeyErrorCode.CODE_12312) { /* 403: potential key misuse, log security event */ } } Prevention
- Normalize loginId to one canonical string form at issuance and at check time
- Treat 12312 as suspicious activity and alert, do not just return 403
When it happens
Trigger: Calling checkApiKeyLoginId(apiKey, loginId) where the key was created for loginId A but the request context/login claims loginId B. Comparison is string-based (String.valueOf on both sides).
Common situations: User A's key used against user B's session (potential credential leakage or client bug); type mismatch such as Integer 10001 vs Long 10001 vs String "10001" usually still matches after stringification, but a padded/formatted id ("010001") will not; key stored under a different account id after data migration.
Related errors
AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14).
Data as JSON: /api/errors/c5ab53b2056539d5.
Report an issue: GitHub.