首页 > 解决方案 > 将 Realm 角色和资源角色与 Keycloak/SpringSecurity 一起使用

问题描述

我正在尝试在带有 spring-security 和 keycloak 的 java 应用程序中同时使用领域和资源角色。不幸的是,keycloak 将仅根据以下值返回一个或另一个:

keycloak.use-resource-role-mappings=true

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

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

先感谢您。

标签: javaspring-securityrealmkeycloak

解决方案


当我在 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();
    }

感谢您的帮助亚历山大!


推荐阅读