Keycloak多资源URI映射下权限执行异常问题咨询
问题背景
我正在使用Keycloak(21.0.0)为Spring Boot(2.7.10)应用管理授权,已配置部分资源仅允许特定用户访问,效果正常。现在希望管理员能访问所有资源,但遇到了权限问题。
Keycloak配置详情
授权设置(Authorization - Settings)
- 决策策略(Decision strategy): Affirmative
资源(Authorization - Resources)
- 名称: all comments
- URIs:
/api/comments/* - 授权范围(Authorization scopes): GET
- URIs:
- 名称: first comment
- URIs:
/api/comments/1 - 授权范围(Authorization scopes): GET
- URIs:
范围(Authorization - Scopes)
- 名称: GET
策略(Authorization - Policies)
- 角色策略(role policy)
- 名称: admin
- 关联角色: admin
- 用户策略(user policy)
- 名称: fubar
- 关联用户: fubar
权限(Authorization - Permissions)
- 基于范围的权限(Scope based)
- 名称: admin_can_read_all_comments
- 关联资源: all comments
- 授权范围: GET
- 关联策略: admin
- 基于范围的权限(Scope based)
- 名称: fubar_can_read_first_comment
- 关联资源: first comments
- 授权范围: GET
- 关联策略: fubar
客户端授权评估结果
- 用户
fubar:对all_comments资源评估为DENY,对first_comment资源评估为PERMIT - 管理员:对
all_comments资源评估为PERMIT,对first_comment资源评估为DENY
疑问
我预期fubar和管理员都能GET /api/comments/1,但实际管理员访问该路径时返回403。请问此行为是否符合预期?
另外,我猜测该行为与keycloak-policy-enforcer的实现有关,想了解当一个URI映射到多个结果不同的资源时,策略执行器会如何处理?
Spring Boot配置
keycloak: securityConstraints: - authRoles: - "*" securityConstraints[0]: securityCollections[0]: patterns[0]: /* principal-attribute: preferred_username auth-server-url: http://kc-host:8080/auth realm: my-realm resource: my-authz-client bearer-only: true credentials: secret: s3cr3t policy-enforcer-config: http-method-as-scope: true lazy-load-paths: true enforcement-mode: enforcing path-cache-config: lifespan: 0
解答
1. 该行为是否符合预期?
是的,当前行为符合Keycloak Policy Enforcer的默认执行逻辑。
核心原因是:/api/comments/1同时匹配了all comments和first comment两个资源,而Policy Enforcer的默认决策策略是UNANIMOUS(要求所有匹配到的资源的授权评估都必须通过)。
虽然管理员对all comments资源的评估是PERMIT,但对first comment资源的评估是DENY(未配置管理员访问该资源的权限),因此整体评估结果为DENY,返回403。
2. 多资源匹配时Policy Enforcer的处理逻辑
当请求URI匹配到Keycloak中多个资源时,Policy Enforcer会对每个匹配资源分别执行授权评估,最终结果由其配置的decision-strategy决定:
UNANIMOUS(默认):所有匹配资源的授权评估都为PERMIT时,才允许访问AFFIRMATIVE:只要有一个匹配资源的授权评估为PERMIT,就允许访问CONSENSUS:超过半数的匹配资源授权评估为PERMIT时,才允许访问
注意:这里的decision-strategy是Policy Enforcer的专属配置,和Keycloak授权设置(Authorization - Settings)里的决策策略不是同一概念——后者针对单个权限内的多策略决策,前者针对多资源匹配时的整体授权结果决策。
解决方案
有两种可行方式实现管理员访问所有资源的需求:
方案1:修改Policy Enforcer的决策策略
在Spring Boot配置的policy-enforcer-config中添加decision-strategy: affirmative,只要有一个匹配资源授权通过就放行:
policy-enforcer-config: http-method-as-scope: true lazy-load-paths: true enforcement-mode: enforcing decision-strategy: affirmative # 添加此行 path-cache-config: lifespan: 0
方案2:给管理员配置所有资源的访问权限
在Keycloak中新增一个权限,让admin策略关联first comment资源的GET权限:
- 新建基于范围的权限,名称例如
admin_can_read_first_comment - 关联资源:
first comment - 授权范围:GET
- 关联策略:
admin
这样管理员对两个资源的评估都会是PERMIT,即使使用默认的UNANIMOUS策略也能正常访问。
内容的提问来源于stack exchange,提问作者Hans

