Keycloak 得到 401 错误,但是 spring security 不处理这个错误 [英] Keycloak get 401 error, but spring security does not handle this error

查看:61
本文介绍了Keycloak 得到 401 错误,但是 spring security 不处理这个错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题如下.我通过 Keycloak Bearer Spring security 实现了这样的登录

The problem is as follows. I implemented the login through Keycloak Bearer Spring security like this

公共类 KeycloakSecurityConfiguration 扩展 KeycloakWebSecurityConfigurerAdapter {

public class KeycloakSecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
    keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
    auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Override
public void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http.sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .sessionAuthenticationStrategy(sessionAuthenticationStrategy())
            .and()
            .csrf().disable()
            .addFilterBefore(keycloakPreAuthActionsFilter(), LogoutFilter.class)
            .addFilterBefore(keycloakAuthenticationProcessingFilter(),               X509AuthenticationFilter.class)
            .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
            .and()
            .authorizeRequests().antMatchers(Constants.API_BASE_PATH + "/**").authenticated();
    }

}

,当我将授权请求标头发送为空时,keycloak 会抛出错误 401.我无法像这样通过 @ExceptionHandler 捕获:

, when I send the Authorization request header empty, keycloak throws error 401. Which I cannot catch through @ExceptionHandler like this :

@ExceptionHandler(RuntimeException.class)受保护的 ResponseEntity keycloakAuthenticationExceptionn(RuntimeException ex) {返回 buildResponseEntity(new ErrorResponseWrapper(BAD_REQUEST,newMessageResponse(ex.getLocalizedMessage()),ex,ErrorCode.NOT_AUTHORIZED));}.

@ExceptionHandler(RuntimeException.class) protected ResponseEntity keycloakAuthenticationExceptionn(RuntimeException ex) { return buildResponseEntity(new ErrorResponseWrapper(BAD_REQUEST,new MessageResponse(ex.getLocalizedMessage()),ex,ErrorCode.NOT_AUTHORIZED)); } .

推荐答案

KeyCloak 有一个 KeycloakAuthenticationFailureHandler 来处理身份验证失败.我能够通过创建自定义 KeycloakAuthenticationFailureHandler 然后在覆盖我的自定义类的同时解决类似的问题KeycloakAuthenticationProcessingFilter.

KeyCloak has a KeycloakAuthenticationFailureHandler that handles authentication failures. I was able to solve a similar problem by creating a Custom KeycloakAuthenticationFailureHandler then set my Custom class while overriding the KeycloakAuthenticationProcessingFilter.

@Bean
    @Override
    protected KeycloakAuthenticationProcessingFilter keycloakAuthenticationProcessingFilter() throws Exception {
        KeycloakAuthenticationProcessingFilter filter = new KeycloakAuthenticationProcessingFilter(this.authenticationManagerBean());
        filter.setSessionAuthenticationStrategy(this.sessionAuthenticationStrategy());
        filter.setAuthenticationFailureHandler(new CustomKeycloakAuthenticationFailureHandler());
        return filter;
    }

在我的自定义类中...

Inside my Custom Class...

public class CustomKeycloakAuthenticationFailureHandler implements AuthenticationFailureHandler {

public CustomKeycloakAuthenticationFailureHandler() {}

@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
    if (!response.isCommitted()) {
        if (KeycloakCookieBasedRedirect.getRedirectUrlFromCookie(request) != null) {
            response.addCookie(KeycloakCookieBasedRedirect.createCookieFromRedirectUrl((String)null));
        }

        //response.sendError(401, "Unable to authenticate using the Authorization header");
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getOutputStream().println("{ \"error\": \"" + exception.getMessage() + "\" }");
    } else if (200 <= response.getStatus() && response.getStatus() < 300) {
        throw new RuntimeException("Success response was committed while authentication failed!", exception);
    }
}

}

我可以使用响应 OutputStream 来自定义我对客户端的响应.我评论了默认的 KeyCloak response.sendError 行.

I am able to use the response OutputStream to customize my response to the client. I commented the default KeyCloak response.sendError line.

看起来 KeyCloak 在内部处理异常.

It looks like KeyCloak handles the exceptions internally.

这个方案也解决了header:WWW-Authenticate的问题在响应中没有重复.

This solution also solves the issue where the header: WWW-Authenticate is not duplicated in the response.

为 KeyCloak 故障排除打开 DEBUG 帮助:logging.level.org.keycloak=DEBUG

Turning on DEBUG for KeyCloak troubleshooting HELPS: logging.level.org.keycloak=DEBUG

希望这会有所帮助.

这篇关于Keycloak 得到 401 错误,但是 spring security 不处理这个错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆