【问题标题】:How to redirect Spring configuration error handling to my custom one?如何将 Spring 配置错误处理重定向到我的自定义错误处理?
【发布时间】:2020-10-20 18:51:06
【问题描述】:

我想知道是否有一种巧妙的方法可以通过配置在 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 为我做这件事,我不想在每个控制器的每个函数中处理异常,只需将其重定向到我的自定义异常服务即可。 提前考虑

【问题讨论】:

    标签: java spring exception spring-security configuration


    【解决方案1】:

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

    【讨论】:

    • 非常感谢,它似乎工作。但是为什么我不能直接发送我的构想对象?什么抓什么?
    • 这是因为您在 Aspect 中捕获的异常是 403,它作为响应传播回来(如果您不包装它)。您发送的对象在响应正文中发送,这与您的响应的 HTTP 状态不同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 2011-01-29
    • 2010-12-07
    • 1970-01-01
    相关资源
    最近更新 更多