将领域角色和资源角色与 Keycloak/Spring Security 一起使用

Posted

技术标签:

【中文标题】将领域角色和资源角色与 Keycloak/Spring Security 一起使用【英文标题】:Using both Realm roles and ressource roles with Keycloak/SpringSecurity 【发布时间】:2020-05-25 14:12:44 【问题描述】:

我正在尝试在带有 spring-security 和 keycloak 的 java 应用程序中同时使用领域和资源角色。不幸的是,keycloak 只会根据 :

的值返回一个或另一个
keycloak.use-resource-role-mappings=true

您仍然可以使用自定义代码来获得两者,但它会弄乱诸如@PreAuthorize 或spring-boot 方法.isUserInRole 之类的注释,从而导致代码丑陋。

有没有办法覆盖@PreAuthorize 方法或Keycloak 返回的JSON 令牌,以便同时使用领域和资源角色?目前,我的 keyclaok 实现使用自定义方法替换每个方法开头的 @PreAuthorize,它并不漂亮。

提前谢谢你。

【问题讨论】:

你写了什么样的自定义代码弄乱了注释?您应该能够通过编写自定义 JwtAuthenticationConverter (docs.spring.io/spring-security/site/docs/current/api/org/…) 从存储在 JWT 中的领域和资源角色填充 GrantedAuthority 来实现您想要的 对不起,我对此不是很清楚,注释很好,但它们不可用,因为它们只包含一半的角色,我会尝试覆盖 Jwt 以获得干净解决方案我也在尝试以@PreAuthorize("@KeycloakAuthorize.hasKeycloakRole('role')") 的格式在预授权中使用bean,但到目前为止也没有成功 好的,那么 JwtAuthenticationConverter 可能是您最好的选择,因为您可以简单地访问 JWT 并根据需要填充权限,例如:***.com/questions/58205510/… 我会试试这个并发布解决方案,如果它有效,谢谢:) Np,让我知道它是否有效! :) 【参考方案1】:

当我在 SecurityConfig 中使用它时,让它覆盖 KeycloakAuthenticationProvider。这是自定义提供程序的代码

public class CustomKeycloakAuthenticationProvider extends KeycloakAuthenticationProvider 
    private GrantedAuthoritiesMapper grantedAuthoritiesMapper;

    public void setGrantedAuthoritiesMapper(GrantedAuthoritiesMapper grantedAuthoritiesMapper) 
        this.grantedAuthoritiesMapper = grantedAuthoritiesMapper;
    

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException 
        KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) authentication;
        List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();

        for (String role : token.getAccount().getRoles()) 
            grantedAuthorities.add(new KeycloakRole(role));
        

// ADDING THE MODIFICATION AND ENABLING ROLE FROM RESSOURCE

        for (String role : token.getAccount().getKeycloakSecurityContext().getToken().getResourceAccess("CustomApplication").getRoles()) 
            grantedAuthorities.add(new KeycloakRole(role));
        
        return new KeycloakAuthenticationToken(token.getAccount(), token.isInteractive(), mapAuthorities(grantedAuthorities));
    

    private Collection<? extends GrantedAuthority> mapAuthorities(
            Collection<? extends GrantedAuthority> authorities) 
        return grantedAuthoritiesMapper != null
            ? grantedAuthoritiesMapper.mapAuthorities(authorities)
            : authorities;
    

    @Override
    public boolean supports(Class<?> aClass) 
        return KeycloakAuthenticationToken.class.isAssignableFrom(aClass);
    



以及SecurityConfig中的修改

@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) 
        CustomKeycloakAuthenticationProvider keycloakAuthenticationProvider = CustomKeycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    

    private CustomKeycloakAuthenticationProvider CustomKeycloakAuthenticationProvider() 
        return new CustomKeycloakAuthenticationProvider();
    

感谢亚历山大的帮助!

【讨论】:

谢谢@Taarawa。它帮助我解决了使用领域角色的问题。

以上是关于将领域角色和资源角色与 Keycloak/Spring Security 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

基于角色与基于资源的权限访问控制

Apache Shiro - 自定义 jdbc 领域 - 读取角色/权限

探讨 IT 在现代商业智能领域中的新角色

如何通过 REST API 将 Keycloak 领域角色添加到组

VODTO与领域模型的概念

您如何将身份验证、角色和安全性融入您的 DDD?