我正在使用SpringBoot开发一个Web应用程序。一切进展顺利,但我有一点问题:
我无法捕捉到异常。自定义:
public class BadCredentialsException extends RuntimeException {
public BadCredentialsException(String message){
super(message);
}
}
我想在OncePerRequestFilter中抓住它,这个:
@Slf4j
public class AuthExceptionHandlerFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
log.debug("AuthExceptionFilter");
try {
filterChain.doFilter(request, response);
} catch (BadRequestAuthException e) {
log.info("Bad auth request received: {}", e.getMessage());
response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
//===========HERE==========
} catch (BadCredentialsException ex) {
log.info("Bad credentials: {}", ex.getMessage());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage());
}
}
}
我也有AuthFilter,但它不相关。 还有一个DefaultExceptionHandler,它可以捕获所有内容:
@Slf4j
public class DefaultExceptionHandlerFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try{
log.debug("DefaultExceptionHandler");
filterChain.doFilter(request, response);
}catch(RuntimeException e){
log.warn("Internal server error: {}", e.getMessage());
e.printStackTrace();
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}catch (Exception e){
log.error("Unknown exception: {}", e.getMessage());
e.printStackTrace();
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}
所有过滤器均由此配置:
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<DefaultExceptionHandlerFilter> exceptionHandlerFilterBean(){
FilterRegistrationBean<DefaultExceptionHandlerFilter> filter = new FilterRegistrationBean<>();
filter.setFilter(defaultExceptionFilter());
filter.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filter;
}
@Bean
public DefaultExceptionHandlerFilter defaultExceptionFilter(){
return new DefaultExceptionHandlerFilter();
}
@Bean
public FilterRegistrationBean<AuthExceptionHandlerFilter> authExceptionHandlerFilterFilterBean(){
FilterRegistrationBean<AuthExceptionHandlerFilter> filter = new FilterRegistrationBean<>();
filter.setFilter(authExceptionHandlerFilter());
filter.setOrder(1);
return filter;
}
@Bean
public AuthExceptionHandlerFilter authExceptionHandlerFilter(){
return new AuthExceptionHandlerFilter();
}
@Bean
public FilterRegistrationBean<AuthFilter> authFilterBean (AccessTokenService authService){
FilterRegistrationBean<AuthFilter> authFilter = new FilterRegistrationBean<>();
authFilter.setFilter(loginFilter(authService));
authFilter.setOrder(2);
return authFilter;
}
@Bean
public AuthFilter loginFilter(AccessTokenService authService){
return new AuthFilter(authService);
}
}
以下方法抛出异常:(由服务调用,由@RestController调用)
private SkyXpUser getAuthenticatedUser(LoginRequest loginRequest){
SkyXpUser user = userService.getUserByName(loginRequest.getUserName());
if(user == null){
throw new BadCredentialsException("User cannot be found. Username: " + loginRequest.getUserName());
}
if(!user.getPassword().equals(loginRequest.getPassword())){
throw new BadCredentialsException("Password is incorrect.");
}
return user;
}
当我输入不存在的用户名或错误的电子邮件时,我得到以下堆栈跟踪:
2018-05-29 19:23:16.841 ERROR 8924 --- [nio-8080-exec-3] s.filter.DefaultExceptionHandlerFilter : Unknown exception: Request processing failed; nested exception is skyxplore.auth.domain.exception.BadCredentialsException: User cannot be found. Username: asad
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is skyxplore.auth.domain.exception.BadCredentialsException: User cannot be found. Username: asad
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at skyxplore.filter.AuthFilter.doFilterInternal(AuthFilter.java:51)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at skyxplore.filter.AuthExceptionHandlerFilter.doFilterInternal(AuthExceptionHandlerFilter.java:22)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at skyxplore.filter.DefaultExceptionHandlerFilter.doFilterInternal(DefaultExceptionHandlerFilter.java:19)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: skyxplore.auth.domain.exception.BadCredentialsException: User cannot be found. Username: asad
at skyxplore.auth.service.AccessTokenService.getAuthenticatedUser(AccessTokenService.java:46)
at skyxplore.auth.service.AccessTokenService.login(AccessTokenService.java:31)
at skyxplore.auth.controller.LoginController.login(LoginController.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
... 53 more
堆栈跟踪显示所有3个过滤器都被称为,而 DefaultExceptionHandler&#34;&#34;异常&#34; catch部分捕获了异常,而不是&#34; RuntimeException&#34;之一。
虽然AuthFilter&#34; BadCredentialsException&#34; part应该捕获此异常,一旦它是BadCredentialsException。或者DefaultExceptionHandler&#34; RuntimeException&#34;部分,因为BadCredentialsException扩展了RuntimeException。
黑客在这里发生了什么?我该如何解决?
答案 0 :(得分:1)
如果我理解正确,您尝试从控制器处理异常。您需要从控制器处理异常的东西。
GlobalHandler:
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(value = BadCredentialsException.class)
public ResponseEntity handleAllExceptions(BadCredentialsException ex){
//DO Something
return new ResponseEntity("Error", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
有不同的方式可以看到: https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc 或What are the advantages of @ControllerAdvice over @ExceptionHandler or HandlerExceptionResolver for handling exceptions?