在 Keycloak/SpringSecurity 中使用 Realm 角色和资源角色

Taa*_*enb 4 java spring-security realm keycloak

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

keycloak.use-resource-role-mappings=true
Run Code Online (Sandbox Code Playgroud)

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

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

先感谢您。

Taa*_*enb 5

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


}
Run Code Online (Sandbox Code Playgroud)

以及 SecurityConfig 中的修改

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

    private CustomKeycloakAuthenticationProvider CustomKeycloakAuthenticationProvider() {
        return new CustomKeycloakAuthenticationProvider();
    }
Run Code Online (Sandbox Code Playgroud)

谢谢亚历山大的帮助!