Authentication Events

对于每个身份验证成功或失败,都会分别触发 AuthenticationSuccessEventAuthenticationFailureEvent

For each authentication that succeeds or fails, a AuthenticationSuccessEvent or AuthenticationFailureEvent, respectively, is fired.

要侦听这些事件,必须首先发布 AuthenticationEventPublisher。Spring Security 的 DefaultAuthenticationEventPublisher 非常适合用作该用途:

To listen for these events, you must first publish an AuthenticationEventPublisher. Spring Security’s DefaultAuthenticationEventPublisher works fine for this purpose:

  • Java

  • Kotlin

@Bean
public AuthenticationEventPublisher authenticationEventPublisher
        (ApplicationEventPublisher applicationEventPublisher) {
    return new DefaultAuthenticationEventPublisher(applicationEventPublisher);
}
@Bean
fun authenticationEventPublisher
        (applicationEventPublisher: ApplicationEventPublisher?): AuthenticationEventPublisher {
    return DefaultAuthenticationEventPublisher(applicationEventPublisher)
}

然后可以使用 Spring 的 @EventListener 支持:

Then you can use Spring’s @EventListener support:

  • Java

  • Kotlin

@Component
public class AuthenticationEvents {
	@EventListener
    public void onSuccess(AuthenticationSuccessEvent success) {
		// ...
    }

    @EventListener
    public void onFailure(AbstractAuthenticationFailureEvent failures) {
		// ...
    }
}
@Component
class AuthenticationEvents {
    @EventListener
    fun onSuccess(success: AuthenticationSuccessEvent?) {
        // ...
    }

    @EventListener
    fun onFailure(failures: AbstractAuthenticationFailureEvent?) {
        // ...
    }
}

虽然类似于 AuthenticationSuccessHandlerAuthenticationFailureHandler,但这些支持很不错,因为可以将它们独立于 servlet API 使用。

While similar to AuthenticationSuccessHandler and AuthenticationFailureHandler, these are nice in that they can be used independently from the servlet API.

Adding Exception Mappings

默认情况下,DefaultAuthenticationEventPublisher 为以下事件发布 AuthenticationFailureEvent

By default, DefaultAuthenticationEventPublisher publishes an AuthenticationFailureEvent for the following events:

Exception

Event

BadCredentialsException

AuthenticationFailureBadCredentialsEvent

UsernameNotFoundException

AuthenticationFailureBadCredentialsEvent

AccountExpiredException

AuthenticationFailureExpiredEvent

ProviderNotFoundException

AuthenticationFailureProviderNotFoundEvent

DisabledException

AuthenticationFailureDisabledEvent

LockedException

AuthenticationFailureLockedEvent

AuthenticationServiceException

AuthenticationFailureServiceExceptionEvent

CredentialsExpiredException

AuthenticationFailureCredentialsExpiredEvent

InvalidBearerTokenException

AuthenticationFailureBadCredentialsEvent

发布者进行确切的 Exception 匹配,这意味着这些异常的子类也不会生成事件。

The publisher does an exact Exception match, which means that sub-classes of these exceptions do not also produce events.

为此,可能希望通过 setAdditionalExceptionMappings 方法为发布者提供其他映射:

To that end, you may want to supply additional mappings to the publisher through the setAdditionalExceptionMappings method:

  • Java

  • Kotlin

@Bean
public AuthenticationEventPublisher authenticationEventPublisher
        (ApplicationEventPublisher applicationEventPublisher) {
    Map<Class<? extends AuthenticationException>,
        Class<? extends AbstractAuthenticationFailureEvent>> mapping =
            Collections.singletonMap(FooException.class, FooEvent.class);
    AuthenticationEventPublisher authenticationEventPublisher =
        new DefaultAuthenticationEventPublisher(applicationEventPublisher);
    authenticationEventPublisher.setAdditionalExceptionMappings(mapping);
    return authenticationEventPublisher;
}
@Bean
fun authenticationEventPublisher
        (applicationEventPublisher: ApplicationEventPublisher?): AuthenticationEventPublisher {
    val mapping: Map<Class<out AuthenticationException>, Class<out AbstractAuthenticationFailureEvent>> =
            mapOf(Pair(FooException::class.java, FooEvent::class.java))
    val authenticationEventPublisher = DefaultAuthenticationEventPublisher(applicationEventPublisher)
    authenticationEventPublisher.setAdditionalExceptionMappings(mapping)
    return authenticationEventPublisher
}

Default Event

还可以提供一个 catch-all 事件,以便在出现任何 AuthenticationException 时触发:

You can also supply a catch-all event to fire in the case of any AuthenticationException:

  • Java

  • Kotlin

@Bean
public AuthenticationEventPublisher authenticationEventPublisher
        (ApplicationEventPublisher applicationEventPublisher) {
    AuthenticationEventPublisher authenticationEventPublisher =
        new DefaultAuthenticationEventPublisher(applicationEventPublisher);
    authenticationEventPublisher.setDefaultAuthenticationFailureEvent
        (GenericAuthenticationFailureEvent.class);
    return authenticationEventPublisher;
}
@Bean
fun authenticationEventPublisher
        (applicationEventPublisher: ApplicationEventPublisher?): AuthenticationEventPublisher {
    val authenticationEventPublisher = DefaultAuthenticationEventPublisher(applicationEventPublisher)
    authenticationEventPublisher.setDefaultAuthenticationFailureEvent(GenericAuthenticationFailureEvent::class.java)
    return authenticationEventPublisher
}