return ResponseEntity<>(HttpStatus.UNAUTHORIZED) 在 Spring 安全基本身份验证中身份验证失败时如何?

How can I return ResponseEntity<>(HttpStatus.UNAUTHORIZED) when Authentication failed in Spring security basic authentication?

我在我的微服务中使用 spring 安全基本身份验证来对客户端进行身份验证,我向消费者提供了我将 return 响应作为 ResponseEntity<>(HttpStatus.XXX) .对于除 401(未授权)之外的所有其他代码,我可以从其余控制器实现此目的,因为 BasicAuthenticationEntryPoint 过滤器正在处理此问题并在请求中没有授权详细信息时给出响应 header。在这种情况下,我如何 return 作为 ResponseEntity<>(HttpStatus.UNAUTHORIZED) 的响应?

我扩展了 BasicAuthenticationEntryPoint 以将我自己的身份验证入口点自定义为 MyBasicAuthenticationEntryPoint。然后抛出异常并尝试从@ExceptionHandler 进行处理。但是,这是行不通的。另外,我用 @ControllerAdvice 注释 class 并读到这将处理仅从控制器抛出的异常。并且,@ExceptionHandler 将在 DispatcherServlet 之后处理异常,而在我的情况下,请求未到达控制器,因为请求中缺少授权详细信息 header.

我在这里所能做的就是在 HttpServletResponse 中包含我的响应 header 和响应状态。我想知道当客户端尝试将 return 类型期望为 ResponseEntity<>(HttpStatus.XXX).

时是否会由客户端处理

在 WebSecurityConfigurerAdapter 扩展的配置方法中定义了我的自定义身份验证入口点 class。

@Configuration
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyBasicAuthenticationEntryPoint authenticationEntryPoint;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().
                authorizeRequests()
                .antMatchers(HttpMethod.POST)
                .authenticated()
                .antMatchers("/api-docs",  "/swagger*/**")
                .permitAll()
                .and()

.httpBasic().authenticationEntryPoint(authenticationEntryPoint)
                ;


        http.headers().frameOptions().disable();
    }
}

如下创建我的自定义身份验证入口点,

@Component
public class MyBasicAuthenticationEntryPoint extends 
BasicAuthenticationEntryPoint {

    @Override
    public void commence
      (HttpServletRequest request, HttpServletResponse response, 
AuthenticationException authEx) 
      throws IOException, ServletException {
        System.out.println("Child Class");
        throw new UnauthorizedException("unauthorized");
        //response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}

通过扩展 RuntimeException class 定义了 UnauthorizedException class。

public class UnauthorizedException  extends RuntimeException {
 public UnauthorizedException(String message) {
 super(message);
 }
}

在 ResponseEntityExceptionHandler extended class 中处理上述异常,如下所示,

@ControllerAdvice
@RestController
public class CustomizedResponseEntityExceptionHandler extends 
ResponseEntityExceptionHandler {
  @ExceptionHandler(UnauthorizedException.class)
  public final ResponseEntity<Void> 
handleNotFoundException(UnauthorizedException ex, WebRequest request) {
      System.out.println("handling 401");
      return new ResponseEntity<>((HttpStatus.UNAUTHORIZED));
 }
}

我希望 return ResponseEntity<>(HttpStatus.UNAUTHORIZED),但 MyBasicAuthenticationEntryPoint 正在使用 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED).

编写响应

CustomizedResponseEntityExceptionHandler 仅处理在您的控制器中遇到的异常,此 @ControllerAdvice 是 self-explanatory。

您错误配置了 authEntryPoint,请参阅此 answer 了解如何正确配置它。

实现你想要的,可以在MyBasicAuthenticationEntryPoint.commence

中直接写response