Использование ролей Realm и ролей ресурсов с Keycloak / SpringSecurity - PullRequest
0 голосов
/ 10 февраля 2020

Я пытаюсь использовать роли как области, так и ресурса в приложении java с Spring-Security и Keycloak. К сожалению, keycloak будет возвращать только одно или другое в зависимости от значения:

keycloak.use-resource-role-mappings=true

Вы можете получить и то, и другое с помощью пользовательского кода, но в нем запутаны аннотации, такие как @PreAuthorize или метод spring-boot. isUserInRole, что приводит к уродливому коду.

Есть ли способ переопределить либо метод @PreAuthorize, либо возврат ключа токена JSON, чтобы использовать роли как области, так и ресурса? В настоящее время моя реализация keyclaok использует собственный метод, заменяющий @PreAuthorize в начале каждого метода, и это не очень красиво.

Заранее спасибо.

1 Ответ

1 голос
/ 10 февраля 2020

Получил работу, переопределяя KeycloakAuthenticationProvider, как я использовал его в SecurityConfig. Вот код для кастомного провайдера

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

Спасибо за помощь, Александр!

...