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

  1. Verify which loginId the key was issued to: saApiKeyTemplate.getApiKey(apiKey).getLoginId()
  2. 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
  3. 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

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.