You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keycloak保护REST API遇403错误(!role)的问题咨询

问题:Keycloak防护REST API出现403(!role)错误

我已经用Keycloak给REST API做了安全防护,完成认证后访问API却碰到403错误,提示:

403 error. Unable to access rest api. Reason !role.

我原本以为用*代表任意角色,配置代码如下:

ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler(); 
context.setSecurityHandler(securityHandler); 
securityHandler.addRole("*"); 
ConstraintMapping constraintMapping = new ConstraintMapping(); 
constraintMapping.setPathSpec("/*"); 
Constraint constraint = new Constraint(); 
constraint.setAuthenticate(true); 
constraint.setRoles(new String[]{"*"}); 

想问问是我用*代表任意角色的假设错了,还是这个错误有别的含义?

JettyKeycloakAuthenticator的日志内容如下:

2018-05-24 12:55:52,253 [DEBUG] [ers.PreAuthActionsHandler(handleRequest )] - adminRequest http://localhost:7100/api/v1/design/test
2018-05-24 12:55:52,254 [DEBUG] [TokenRequestAuthenticator(thenticateToken)] - Verifying access_token
2018-05-24 12:55:52,255 [DEBUG] [TokenRequestAuthenticator(thenticateToken)] - successful authorized
2018-05-24 12:55:52,255 [DEBUG] [JettyRequestAuthenticator(rAuthentication)] - Completing bearer authentication. Bearer roles: [uma_authorization]
2018-05-24 12:55:52,255 [DEBUG] [ters.RequestAuthenticator(eAuthentication)] - User '8f9381df-2f7e-4ff8-9ef5-2123b03db3c9' invoking 'http://localhost:7100/api/v1/design/test' on client 'my_server'
2018-05-24 12:55:52,255 [DEBUG] [ters.RequestAuthenticator(authenticate )] - Bearer AUTHENTICATED
2018-05-24 12:55:52,255 [DEBUG] [thenticatedActionsHandler(handledRequest )] - AuthenticatedActionsValve.invoke http://localhost:7100/api/v1/design/test


问题分析与解决方案

首先,你的假设确实错了——Jetty的Constraint里用"*"并不代表任意角色,它会把*当成一个具体的角色名称来校验。从日志里能看到,你的Bearer token里只有uma_authorization这个角色,而Jetty在检查时会去找名为*的角色,自然匹配失败,返回403。

那要实现“任意已认证用户都能访问”的需求,有两种靠谱方式:

方式一:只要求认证,不指定角色

把constraint.setRoles(new String[]{"*"});这行删掉,或者设置为空数组。因为当你开启constraint.setAuthenticate(true);时,只要用户完成认证,即使没有指定任何角色,也能通过校验。修改后的代码片段:

Constraint constraint = new Constraint(); 
constraint.setAuthenticate(true); 
// 移除setRoles这行,或者设置为new String[]{}

方式二:动态添加用户的实际角色

如果你的场景需要基于角色控制,但想允许用户拥有的所有角色都能访问,可以从Keycloak的认证信息里提取用户的角色,再添加到securityHandler中。比如:

// 从请求中获取Keycloak认证信息
KeycloakPrincipal<?> principal = (KeycloakPrincipal<?>) request.getUserPrincipal();
AccessToken accessToken = principal.getKeycloakSecurityContext().getToken();
Set<String> roles = accessToken.getRealmAccess().getRoles();

// 将用户所有角色添加到securityHandler
for (String role : roles) {
    securityHandler.addRole(role);
}

// 约束中设置这些角色
constraint.setRoles(roles.toArray(new String[0]));

另外,从日志里看到你的token只有uma_authorization角色,如果你本来期望有其他角色,还得检查下Keycloak的配置:

  • 确认客户端的**“Full Scope Allowed”**是否开启,或者是否手动添加了需要的角色到客户端范围
  • 检查用户是否被正确分配了对应的Realm角色或客户端角色

最后提一句,Jetty的ConstraintSecurityHandler角色匹配是严格的字符串匹配,别想用通配符偷懒哦~


内容的提问来源于stack exchange,提问作者tryingToLearn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:00:26