首页 > 解决方案 > 如何将 Spring 配置错误处理重定向到我的自定义错误处理?

问题描述

我想知道是否有一种巧妙的方法可以通过配置在 Spring 中处理异常。我可以直接从扩展 WebSecurityConfigurerAdapter 接口的类中抛出异常,但在我看来,如果我使用 exceptionHandling 方法,我无法使用它发送消息。但是,如果我删除了 conf,我就无法进行全局自定义异常配置。我想知道 Spring 是否可以将异常处理重定向到 @ControllerAdvice?

现在我的代码看起来像这样(我从代码中删除了无用的部分)

配置

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@FieldDefaults(level = PRIVATE, makeFinal = true)
class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private AuthFailureHandler authFailureHandler;

private static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
        new AntPathRequestMatcher("**", "OPTIONS"), // allow prefligh for now in debug 
        new AntPathRequestMatcher("/public/**")
);
private static final RequestMatcher PROTECTED_URLS = new NegatedRequestMatcher(PUBLIC_URLS);

TokenAuthenticationProvider provider;

SecurityConfig(AuthFailureHandler authFailureHandler, final TokenAuthenticationProvider provider) {
    super();
  this.authFailureHandler = authFailureHandler;
  this.provider = requireNonNull(provider);
}

@Override
protected void configure(final AuthenticationManagerBuilder auth) {
    auth.authenticationProvider(provider);
}

@Override
public void configure(final WebSecurity web) {
    web.ignoring().requestMatchers(PUBLIC_URLS);
}

@Override
protected void configure(final HttpSecurity http) throws Exception {
    http
            .sessionManagement()
            .sessionCreationPolicy(STATELESS)
            .and()
            .exceptionHandling()
            .defaultAuthenticationEntryPointFor(forbiddenEntryPoint(), PROTECTED_URLS)
             .and()
            .authenticationProvider(provider)
            .authorizeRequests()
            .requestMatchers(PROTECTED_URLS)
            .authenticated()
          
}

这里处理异常的代码是

 .exceptionHandling()
            .defaultAuthenticationEntryPointFor(forbiddenEntryPoint(), PROTECTED_URLS)
             .and()
            .authenticationProvider(provider)

            .authorizeRequests()
            .requestMatchers(PROTECTED_URLS)
            .authenticated()

问题是如果我引发异常,它会由默认的 ExceptionHandling 处理,我无法设置自定义错误消息或 http 错误代码,从而导致默认错误处理。如果我删除它,我必须在任何地方引发异常!

控制器 中的一个,但是像这样你有一个样本

@RestController
@RequestMapping("/public/users")
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@CrossOrigin
public class UserPublic {

@NonNull UserAuthenticationService authenticationService;

@PostMapping(value = "/login",
      consumes="application/json",
      produces="application/json")
UserDTO login(@RequestBody shortDTO dto) throws UserNotFoundException {

  UserDTO userDTO = authenticationService.login(dto.email, dto.password);
  if (userDTO == null) throw new UserNotFoundException("no User found with this email / password combination");

  return userDTO;
}

例外

 public class UserNotFoundException extends Exception {


 public UserNotFoundException(String no_user_found) {
   super(no_user_found);
 }

}

异常处理程序

@ControllerAdvice
public class ServiceExceptionHandler extends ResponseEntityExceptionHandler  {

  @ExceptionHandler(value = {UserNotFoundException.class })
  @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
  public ApiErrorResponse unknownException(Exception ex, WebRequest req) {
    System.out.println("damn here we go again");
    ex.printStackTrace();
    return new ApiErrorResponse(ex.getMessage());
  }
}

启用或禁用 conf 的 StackTrace 是

com.application.controller.user.UserNotFoundException: no User found with this email / password combination
....

但是使用 conf 我收到 403 错误而不是 500 (将更改但需要不同的错误代码)并且正文是空的。我怎样才能将两者结合起来?对于受保护的路由,我也有同样的问题,如果用户已登录并让 Spring 为我做这件事,我不想在每个控制器的每个函数中处理异常,只需将其重定向到我的自定义异常服务。提前致谢

标签: javaspringexceptionspring-securityconfiguration

解决方案


在您的 ExceptionHandler 建议中,您需要将 ApiErrorResponse 包装到 ResponseEntity 中并返回 new ResponseEntity<>(new ApiErrorResponse(ex.getMessage()), HttpStatus.BAD_REQUEST);


推荐阅读