在 Spring MVC 中处理 JWT 异常

Posted

技术标签:

【中文标题】在 Spring MVC 中处理 JWT 异常【英文标题】:Handling JWT Exception in Spring MVC 【发布时间】:2016-12-30 23:21:10 【问题描述】:

我正在尝试在我们的 REST Api 上实现令牌身份验证,目前我指的是 article。在文章中,它讨论了在创建令牌时使用了 JWT,但我目前的问题是,每次将无效令牌传递给我的应用程序时,都会创建一个异常,即 JwtException.class,我想捕获该异常使用我的全局异常处理程序类。我还尝试将 JwtException 包装在我的应用程序的异常类上,但无济于事,异常没有被捕获。

@ControllerAdvice
public class GlobalExceptionHandler 

@ExceptionHandler(value=JwtException.class)
public ResponseEntity<?> handleTokenException(JwtException e)
    return new ResponseEntity<Object>(HttpStatus.UNAUTHORIZED);


@ExceptionHandler(value=InvalidAuthTokenException.class)
public ResponseEntity<?> handleTokenException(InvalidAuthTokenException e)
    return new ResponseEntity<Object>(HttpStatus.UNAUTHORIZED);
    

【问题讨论】:

【参考方案1】:

您的 GlobalExceptionHandler 并不是真正的全局性,它只会捕获您的控制器中发生的异常(因此 ControllerAdvice),您遇到的异常发生在 servlet 过滤器中,这就是 Spring Security几乎完成了所有的工作。这个小图表可能有助于解释我在说什么:

PreFilters

Controller

PostFilters

幸运的是,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,抱歉我忘记在解密 JWT 时添加,如果您遇到异常,您需要将该异常作为 AuthenticationException 重新抛出(因为这是 ExceptionTranslationFilter 正在寻找的)。我更新了我的答案以显示这一点。 我应用了您在编辑中声明的更改,但我的 REST API 没有返回 401 状态,而是由于抛出身份验证异常而收到错误 500。我为此提出了一个新问题。请参阅***.com/questions/39207743/…。谢谢 AuthenticationException 是抽象的,无法实例化。

以上是关于在 Spring MVC 中处理 JWT 异常的主要内容,如果未能解决你的问题,请参考以下文章

使用Spring MVC统一异常处理实战

如何在 Spring MVC 中针对 HTML 和 JSON 请求以不同方式处理异常

如何在 Spring MVC 中针对 HTML 和 JSON 请求以不同方式处理异常

在 Spring MVC 应用程序中从异常记录更改为异常处理的最简单方法是啥?

Spring MVC异常处理

Spring MVC统一异常处理