Spring 安全添加 ApplicationEventListener 到 ExpiredJwtException

Spring security add ApplicationEventListener to ExpiredJwtException

我已经通过使用 ApplicationListener<AuthenticationFailureBadCredentialsEvent> 实现了 AuthenticationFailureListener 登录失败,我所有的 Bad Credentials 事件都在同一个 class 中处理,非常方便,我尝试添加一个监听器到 ExpiredJwtExceptionSignatureException 但我无法确定触发了哪个事件,我已经尝试过 -

@Component
public class ApplicationEventListener implements ApplicationListener<ApplicationEvent>{

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println(event.toString()); //not printed when ExpiredJwtException thrown
    }
}

捕获所有 ApplicationEvent 但是当其中一个异常发生时,方法 onApplicationEvent 不会被触发。 我可以捕获此异常,但我想全局处理它们,就像 BadCredentialsExceptionAuthenticationFailureBadCredentialsEvent 处理一样。 尝试过 AuthenticationFailureExpiredEvent -

@Component
public class ApplicationEventListener implements ApplicationListener<AuthenticationFailureExpiredEvent>{

    @Override
    public void onApplicationEvent(AuthenticationFailureExpiredEvent event) {
        System.out.println("Expired!!"); //same result
    }
}

但还是不行。

我认为在捕获异常时发布 ApplicationEvent 的最简单方法是使用 ApplicationEventPublisher。无需使用此方法实现 ApplicationEvent,因为它将任何对象包装到 PayloadApplicationEvent 中,您可以在 ApplicationEventListener 中使用并对其进行操作。这适用于 Spring 4.2,这是官方的 link:https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2

我不确定这一点,我必须检查来源,但是:可能是 未发出 ExpiredJwtException 的应用程序事件或SignatureException.

可能的解决方案是:

  1. 自己发布事件:正如您提到的,您可以捕获这些异常,因此一个简单的解决方案是捕获它们然后发出所需的事件。您只需要自动装配 ApplicationEventPublisher 然后调用 publishEvent(event).

  2. 使用 Filter 在一个地方捕获和处理异常。

解决方案 2 示例:

public class AuthFailureFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            chain.doFilter(request, response);
        } catch (ExpiredJwtException | SignatureException exception) {
            handle(exception);
        }
    }
}