你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