【问题标题】:Spring Boot KeyCloak not invoking success handlerSpring Boot KeyCloak 未调用成功处理程序
【发布时间】:2022-01-26 17:53:49
【问题描述】:

我在我的应用程序中使用 Spring Boot KeyCloak 来连接 KeyCloak。但是我有一个没有被调用的自定义成功处理程序。我不确定为什么。这是我的代码:

SecurityConfiguration.java:

@KeycloakConfiguration
public class SecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {

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

    @Bean
    public KeycloakSpringBootConfigResolver keycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }

    @Bean
    @Primary
    @Override
    protected KeycloakAuthenticationProcessingFilter keycloakAuthenticationProcessingFilter() throws Exception {
        KeycloakAuthenticationProcessingFilter filter = new KeycloakAuthenticationProcessingFilter(authenticationManagerBean());
        filter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy());
        filter.setAuthenticationSuccessHandler(successHandler());
        filter.setAuthenticationFailureHandler(failureHandler());
        return filter;
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.csrf().disable().authorizeRequests()
            .antMatchers("/**").authenticated();
    }

    @NotNull
    @Bean
    public KeyCloakAuthSuccessHandler successHandler() {
        return new KeyCloakAuthSuccessHandler(new SavedRequestAwareAuthenticationSuccessHandler());
    }

    @NotNull
    @Bean
    public KeyCloakAuthFailureHandler failureHandler() {
        return new KeyCloakAuthFailureHandler();
    }

}

在我的KeyCloakAuthSuccessHandler.java 中,我有:

@Slf4j
public class KeyCloakAuthSuccessHandler extends KeycloakAuthenticationSuccessHandler {

    @Autowired
    ObjectMapper mapper;

    public KeyCloakAuthSuccessHandler(AuthenticationSuccessHandler fallback) {
        super(fallback);
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException, ServletException {
        log.error("inside success handler");
        if (authentication.getPrincipal() instanceof KeycloakPrincipal) {
            AccessToken token = ((KeycloakPrincipal<?>) authentication.getPrincipal()).getKeycloakSecurityContext().getToken();
            // do other stuff
        }
    }
}

上面的代码没有调用成功处理程序,但是类似的失败处理程序正在工作并被调用。

【问题讨论】:

  • 为什么要用@Slf4j 注释类?
  • 用于在我的成功处理程序中记录内容
  • @mifol68042 您是否尝试过一次又一次地不传递承载/基本(无论配置哪个)标头进行测试?即使在这两种情况下,它都不会通过成功处理程序吗?因为代码看起来很正确。

标签: spring-security keycloak


【解决方案1】:

正如在 cmets 中所讨论的,这是因为在 Keycloak 的非交互式(非人类方式 - 承载/基本)登录期间未调用成功处理程序。如果您想每次都调用成功处理程序而不考虑登录方式,请通过扩展它来编写自定义KeycloakAuthencticationProcessingFilter,并通过覆盖它来更改原始this line

一个粗略的例子如下:

public class CustomKeycloakAuthenticationProcessingFilter extends KeycloakAuthenticationProcessingFilter {
    
    public CustomKeycloakAuthenticationProcessingFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    public CustomKeycloakAuthenticationProcessingFilter(AuthenticationManager authenticationManager, RequestMatcher requiresAuthenticationRequestMatcher) {
        super(authenticationManager, requiresAuthenticationRequestMatcher);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {
        // Line of importance down here
        if (authResult instanceof KeycloakAuthenticationToken) {
            super.successfulAuthentication(request, response, chain, authResult);
            return;
        }
        // whatever spring-boot-keycloak does copy paste here
    }
}

【讨论】:

    【解决方案2】:

    我认为您必须使用您的 KeyCloakAuthSuccessHandler 编写自己的 KeycloakAuthenticationProcessingFilter。

    https://github.com/keycloak/keycloak/blob/main/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilter.java

    你不能注入你的 KeyCloakAuthSuccessHandler。

    【讨论】:

    • 我已经写了一个处理过滤器。请检查上面的代码。它通过在websecurityconfig 本身中使用@Bean 注释来完成
    • 是的,你是对的
    • 你必须调试才能看到真正发生了什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-20
    • 1970-01-01
    • 2013-11-11
    • 2019-10-09
    • 2012-09-30
    • 2015-06-03
    • 2021-03-18
    相关资源
    最近更新 更多