SpringBoot2 配置自定义 AuthenticationEntryPoint 时 BadCredentialsException 失效的问题

需求背景比较简单,就是需要区分以下两种状态:

Basic Auth 认证的场景    返回状态码
没有用户名密码    401
用户名密码错误    403
实现也比较粗暴,通过 Spring Security 的 WebSecurityConfigurerAdapter,配置自定义的 AuthenticationEntryPoint,然后判断异常的类型设置不同的状态,密码错误时的异常为BadCredentialsException,没有用户密码时的异常为InsufficientAuthenticationException,代码如下:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  // omit other configures ......
 
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .authorizeRequests().anyRequest().authenticated()
        .and().httpBasic().authenticationEntryPoint(authenticationEntryPoint());
  }
 
  @Bean
  public AuthenticationEntryPoint authenticationEntryPoint() {
    return (request, response, exception) -> {
      if (exception instanceof BadCredentialsException) {
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
      } else {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
      }
    };
  }
}
之前一直很稳,但是从springboot 1.5.22 迁移到 springboot 2.3.0 之后,问题就来了,之前的代码已经无法区分这两个状态,一直返回的是401.

一顿虎操,发现现象就是 BadCredentialsException 出现时,InsufficientAuthenticationException 也会跟着出现,最终导致client端收到的状态码一直是401。

网上搜索+折腾了半天都没起作用,后来在github上发现了root cause:

Spring security 5 "Bad credentials" exception not shown with errorDetails

 

解决办法也比较容易,给 /error 页面添加权限即可。添加一行代码:

.antMatchers("/error").permitAll()

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .authorizeRequests()
        .antMatchers("/error").permitAll()
        .anyRequest().authenticated()
        .and().httpBasic().authenticationEntryPoint(authenticationEntryPoint());
  }

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页