Quarkus OIDC:从userInfo而非idToken提取角色的实现方法
解决Quarkus从OIDC UserInfo提取角色用于@RolesAllowed的问题
方法1:通过配置直接实现(最简单)
Quarkus OIDC提供了现成的配置项,可直接指定从UserInfo中提取角色,无需编写自定义代码。在application.properties中添加以下配置:
# 指定角色来源为UserInfo quarkus.oidc.roles.source=user-info # 指定UserInfo中存储角色的声明字段名 quarkus.oidc.roles.claim-path=groups
配置完成后,Quarkus会自动从UserInfo的groups字段中提取角色,供@RolesAllowed注解使用。
方法2:自定义角色提取器(适用于复杂逻辑场景)
如果需要对角色做额外的转换或过滤逻辑,可以实现OidcRolesExtractor接口,手动从UserInfo中提取角色:
import io.quarkus.oidc.OidcIdentityProvider; import io.quarkus.oidc.runtime.OidcRolesExtractor; import io.quarkus.security.identity.SecurityIdentity; import jakarta.enterprise.context.ApplicationScoped; import org.eclipse.microprofile.jwt.JsonWebToken; import java.util.Collections; import java.util.HashSet; import java.util.Set; @ApplicationScoped public class CustomUserInfoRolesExtractor implements OidcRolesExtractor { @Override public Set<String> extractRoles(OidcIdentityProvider provider, JsonWebToken jwt, SecurityIdentity identity) { // SecurityIdentity的attributes中包含UserInfo的所有声明 Object groupsAttr = identity.getAttributes().get("groups"); Set<String> roles = new HashSet<>(); if (groupsAttr instanceof Set) { roles.addAll((Set<String>) groupsAttr); } else if (groupsAttr instanceof Iterable) { ((Iterable<?>) groupsAttr).forEach(item -> roles.add(item.toString())); } else if (groupsAttr != null) { roles.add(groupsAttr.toString()); } return roles; } }
然后在配置中指定使用这个自定义提取器:
quarkus.oidc.roles.extractor=com.yourpackage.CustomUserInfoRolesExtractor
关于Augmentor的补充说明
你提到的Augmentor其实也可以实现需求,SecurityIdentityAugmentor的augment方法参数中的SecurityIdentity已经包含了UserInfo的属性,可从中提取角色并添加到身份信息中:
import io.quarkus.security.identity.SecurityIdentity; import io.quarkus.security.identity.SecurityIdentityAugmentor; import jakarta.enterprise.context.ApplicationScoped; import java.util.HashSet; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @ApplicationScoped public class RolesAugmentor implements SecurityIdentityAugmentor { @Override public CompletionStage<SecurityIdentity> augment(SecurityIdentity identity, AugmentorContext context) { Object groupsAttr = identity.getAttributes().get("groups"); Set<String> roles = new HashSet<>(); // 转换groups属性为角色集合,逻辑同自定义提取器 if (groupsAttr instanceof Set) { roles.addAll((Set<String>) groupsAttr); } else if (groupsAttr instanceof Iterable) { ((Iterable<?>) groupsAttr).forEach(item -> roles.add(item.toString())); } else if (groupsAttr != null) { roles.add(groupsAttr.toString()); } // 返回添加了角色的新SecurityIdentity return CompletableFuture.completedFuture(identity.withRoles(roles)); } }
不过这种方式不如前两种直接,因为Quarkus OIDC已经提供了专门的角色提取机制,优先推荐配置或自定义提取器方案。
内容的提问来源于stack exchange,提问作者badnun872
相关产品推荐
相关产品推荐

