dromara/Sa-Token · error · ApiKeyScopeException

12311

12311

Error message

该 API Key 不具备 Scope:

What it means

Thrown by SaApiKeyTemplate.checkApiKeyScope(String, String...) in AND mode: the key passes checkApiKey but its scopes list does not contain one of the required scopes. Code 12311 is the ApiKeyScopeException error code; the exception carries the missing scope.

Source

Thrown at sa-token-plugin/sa-token-apikey/src/main/java/cn/dev33/satoken/apikey/template/SaApiKeyTemplate.java:315

			return true;
		} catch (ApiKeyException e) {
			return false;
		}
	}

	/**
	 * 校验:指定 ApiKey 是否具有指定 Scope 列表 (AND 模式,需要全部具备),如果不具备则抛出异常
	 * @param apiKey ApiKey
	 * @param scopes 需要校验的权限列表
	 */
	public void checkApiKeyScope(String apiKey, String... scopes) {
		ApiKeyModel ak = checkApiKey(apiKey);
		if(SaFoxUtil.isEmptyArray(scopes)) {
			return;
		}
		for (String scope : scopes) {
			if(! ak.getScopes().contains(scope)) {
				throw new ApiKeyScopeException("该 API Key 不具备 Scope:" + scope)
						.setApiKey(apiKey)
						.setScope(scope)
						.setCode(SaApiKeyErrorCode.CODE_12311);
			}
		}
	}

	/**
	 * 判断:指定 ApiKey 是否具有指定 Scope 列表 (OR 模式,具备其一即可),返回 true 或 false
	 * @param apiKey ApiKey
	 * @param scopes 需要校验的权限列表
	 */
	public boolean hasApiKeyScopeOr(String apiKey, String... scopes) {
		try {
			checkApiKeyScopeOr(apiKey, scopes);
			return true;
		} catch (ApiKeyException e) {
			return false;

View on GitHub (pinned to ac2c7f6e94)

Solutions

  1. Re-create the key including the missing scope: createApiKey(loginId, clientToken, timeout, scopes) with the full required set
  2. Check for typos/case mismatch between the scope string required by the code and the one stored on the key
  3. Inspect the stored scopes first: saApiKeyTemplate.getApiKey(apiKey).getScopes()

Example fix

// before
// key created with scopes "userinfo" only
saApiKeyTemplate.checkApiKeyScope(apiKey, "userinfo", "order"); // throws 12311

// after
String key = saApiKeyTemplate.createApiKey(10001, "svc", 3600*24, Arrays.asList("userinfo", "order"));
saApiKeyTemplate.checkApiKeyScope(key, "userinfo", "order");
Defensive patterns

Strategy: validation

Validate before calling

ApiKeyModel ak = saApiKeyTemplate.getApiKey(apiKey);
Set<String> need = new HashSet<>(Arrays.asList("userinfo", "order"));
if (ak == null || !ak.getScopes().containsAll(need)) {
    return forbidden("missing scope");
}

Try / catch

catch (ApiKeyScopeException e) { if (e.getCode() == SaApiKeyErrorCode.CODE_12311) { /* 403 with required scopes listed */ } }

Prevention

When it happens

Trigger: Calling checkApiKeyScope(apiKey, "userinfo", "order") when the key's scopes collection lacks at least one of them (all must be present); annotation-based scope checks on a route hit the same path.

Common situations: Key was issued with scopes ["userinfo"] but the endpoint now requires ["userinfo","pay"]; scope naming mismatch ("user-info" vs "userinfo", case); adding a new required scope to an API without re-issuing keys.

Related errors


AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14). Data as JSON: /api/errors/637beab6eca3c6cc. Report an issue: GitHub.