你GlobalExceptionHandler并非真正全球性的,它只会赶上发生在你的控制器(因此ControllerAdvice)例外,你正在运行到Servlet过滤器是发生的例外,这是在春季安全呢几乎所有的工作。这个小图表可能有助于解释什么,我说什么:
预过滤器< - 进入控制器之前执行,智威汤逊的解密发生在这里
控制器< - ControllerAdvice会赶上这里
后过滤抛出的所有异常< - 退出控制器后执行
幸运的是,Spring Security已经有适当的机制来处理在解密过滤器中的JWT等事情时发生的异常。你会想这样更新你的SpringSecurityConfig。请注意,ExceptionTranslationFilter是之后的您的StatelessAuthenticationFilter(或任何您命名为JWT解密发生的过滤器)之后的重要事项。
@Configuration
@EnableWebSecurity
@Order(2)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
ExceptionTranslationFilter = new ExceptionTranslationFilter(new AuthenticationExceptionHandler());
http.addFilterAfter(new StatelessAuthenticationFilter(tokenAuthenticationService),
ExceptionTranslationFilter.class);
}
}
public class AuthenticationExceptionHandler implements AuthenticationEntryPoint {
public void commence(HttpServletRequest request, HttpServletResponse, AuthenticationException e) throws IOException, ServletException {
//Logic on how to handle JWT exception goes here
}
}
public class StatelessAuthenticationFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
//DECRYPT YOUR JWT
} catch (Exception e) {
throw new AuthenticationException();//If you get an exception wrap it in a AuthenticationException (or a class that extends it)
}
}
}
我试着添加ExceptionTranslationFilter,但仍然有相同的问题。 – anathema
@anathema,对不起,我忘了添加解密你的JWT时,如果你得到一个异常,你需要重新抛出异常作为AuthenticationException(因为这是ExceptionTranslationFilter正在寻找什么)。我更新了我的答案以表明这一点。 –
我应用了您在编辑中声明的更改,但它不是由我的REST API返回401状态,而是由于引发了身份验证异常而导致错误500。对此我创建了一个新问题。请参阅http://stackoverflow.com/questions/39207743/handling-filter-thrown-exceptions-in-spring。谢谢 – anathema