spring 未将异常抛出到全局API错误处理程序

eqoofvh9  于 2024-01-05  发布在  Spring
关注(0)|答案(2)|浏览(159)

我在spring Boot 3.2.0中为全局API错误处理程序定义了class。我添加了bearer token的安全性,我希望返回响应,但它显示14:41:32.831 [http-nio-0.0.0.0-11150-exec-2] ERROR o.a.c.c.C.[Tomcat].[localhost] - Exception Processing ErrorPage[errorCode=0,location=/error]
我写的全局API错误处理类

  1. @ControllerAdvice
  2. @Order(Ordered.HIGHEST_PRECEDENCE)
  3. public class ApiGlobalErrorHandler {
  4. private static final Logger LOG = LoggerFactory.getLogger(ApiGlobalErrorHandler.class.getName());
  5. @ExceptionHandler(UnauthorizedAccessException.class)
  6. @ResponseStatus(value = HttpStatus.UNAUTHORIZED)
  7. @ResponseBody
  8. protected ApiResponseWrapper handleUnauthorizedAccessException(UnauthorizedAccessException ex) {
  9. LOG.error("UnauthorizedAccessException occurred:{},code-{}", ex.getErrorType(), ex.getErrorType().getCode());
  10. return new ApiResponseWrapper(new ApiErrorResponse(HttpStatus.UNAUTHORIZED.value() + "." + API_ID_CODE + "." + ex.getErrorType().getCode(), ex.getErrorType().getMessagge()));
  11. }

字符串
我期待错误响应,但我得到了14:41:32.831 [http-nio-0.0.0.0-11150-exec-2] ERROR o.a.c.c.C.[Tomcat].[localhost] - Exception Processing ErrorPage[errorCode=0,location=/error].如何禁用处理错误页?尝试不使用承载令牌enter image description here堆栈跟踪是:

  1. 14:41:32.831 [http-nio-0.0.0.0-11150-exec-2] ERROR o.a.c.c.C.[Tomcat].[localhost] - Exception Processing ErrorPage[errorCode=0, location=/error]
  2. rs.yettel.roamingbarring.exception.UnauthorizedAccessException: Missing Authorization header
  3. at rs.yettel.roamingbarring.security.ApiKeyAuthFilter.getPreAuthenticatedPrincipal(ApiKeyAuthFilter.java:19)
  4. at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doAuthenticate(AbstractPreAuthenticatedProcessingFilter.java:189)
  5. at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doFilter(AbstractPreAuthenticatedProcessingFilter.java:142)
  6. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  7. at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107)
  8. at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93)
  9. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  10. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
  11. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  12. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
  13. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  14. at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82)
  15. at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69)
  16. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  17. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
  18. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  19. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
  20. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
  21. at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233)
  22. at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191)
  23. at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:352)
  24. at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:268)
  25. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
  26. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
  27. at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
  28. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
  29. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
  30. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
  31. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
  32. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
  33. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
  34. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
  35. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
  36. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
  37. at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:642)
  38. at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:410)
  39. at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:340)
  40. at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:277)
  41. at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:362)
  42. at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:222)
  43. at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:308)
  44. at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:149)
  45. at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
  46. at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
  47. at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340)
  48. at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391)
  49. at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
  50. at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896)
  51. at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744)
  52. at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
  53. at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
  54. at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
  55. at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  56. at java.base/java.lang.Thread.run(Thread.java:833)

puruo6ea

puruo6ea1#

从Spring Security版本6.0开始,框架开始过滤所有调度器类型,例如requestasyncerrorforwardinclude
如果您想在您的场景中排除error调度器类型,您可以配置过滤器链,如下所示:

  1. public SecurityFilterChain customFilterChain(HttpSecurity httpSecurity) throws Exception {
  2. httpSecurity
  3. .authorizeHttpRequests(auth -> auth
  4. .dispatcherTypeMatchers(DispatcherType.ERROR).permitAll()
  5. .requestMatchers("/error").permitAll()
  6. .anyRequest().authenticated()
  7. )
  8. .addFilterBefore(new ApiKeyAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
  9. return httpSecurity.build();
  10. }

字符串
有关此主题的其他信息,请参阅Spring Security文档,链接为:https://docs.spring.io/spring-security/reference/5.8/migration/servlet/authorization.html#switch-filter-all-dispatcher-types。
您的ApiKeyAuthFilter似乎正在引发UnauthorizedAccessException。请务必注意,无法使用@ControllerAdvice处理Filters中抛出的异常。要深入了解自定义Filters中抛出的异常,请参阅此question以获取指导。

已编辑

在检查了你的代码之后,我有几点要强调:
1.如前所述,过滤器中引发的异常不会被@ControllerAdvice处理。要发送自定义错误消息,建议在过滤器中捕获错误并使用HttpServletResponse发送错误代码。我提供了一个示例存储库来演示如何实现这一点,您可以在这里找到:GitHub Repository
1.我注意到你在你的案例中使用了AbstractPreAuthenticatedProcessingFilter。但是,如果你只是覆盖了抽象方法,而这些方法没有访问HttpServletResponse的权限,你将无法使用这种方法发送自定义错误代码和/或消息。在我创建的示例存储库中,你可以观察到CustomSecurityFilter的使用,它扩展了OncePerRequestFilter,并在运行BasicAuthenticationFilter之前添加。这种方法被认为是实现所需功能的更干净的方法。
对于进一步的定制,我建议探索Spring框架中的BasicErrorControllerDefaultErrorAttributes类。此外,您可以参考Sping Boot 官方文档以获取更多信息:Sping Boot 文档。

展开查看全部
bhmjp9jg

bhmjp9jg2#

你有没有在属性文件中尝试:server.error.whitelabel.enabled=false

相关问题