接口类AuthenticationEventPublisher定义了Spring Security中用户授权成功或失败的通知机制.
方法:
//成功时调用
void publishAuthenticationSuccess(Authentication authentication);
//失败时调用
void publishAuthenticationFailure(AuthenticationException exception,
Authentication authentication);
并且提供了一个默认的实现策略类DefaultAuthenticationEventPublisher,同时实现了接口类AuthenticationEventPublisher,ApplicationEventPublisherAware
DefaultAuthenticationEventPublisher在其内部维护一个异常类AuthenticationException和其对应的事件类AbstractAuthenticationFailureEvent的哈希表,方便将异常同授权事件对应起来.
(“成功的原因大都相似,失败的原因各种各样”)
//构造函数中初始化
addMapping(BadCredentialsException.class.getName(),AuthenticationFailureBadCredentialsEvent.class);
addMapping(UsernameNotFoundException.class.getName(),AuthenticationFailureBadCredentialsEvent.class);
addMapping(AccountExpiredException.class.getName(),AuthenticationFailureExpiredEvent.class);
授权成功时发布事件
applicationEventPublisher.publishEvent(new AuthenticationSuccessEvent(authentication));
失败时
Constructor<? extends AbstractAuthenticationEvent> constructor = exceptionMappings.get(exception.getClass().getName());
AbstractAuthenticationEvent event = null;
if (constructor != null) {
try {
event = constructor.newInstance(authentication, exception);
} catch () {
}
}
if (event != null) {
if (applicationEventPublisher != null) {
applicationEventPublisher.publishEvent(event);
}
}
参照测试类DefaultAuthenticationEventPublisherTests可以理解其使用逻辑
publisher = new DefaultAuthenticationEventPublisher();
ApplicationEventPublisher appPublisher = mock(ApplicationEventPublisher.class);
publisher.setApplicationEventPublisher(appPublisher);
Authentication a = mock(Authentication.class);
Exception cause = new Exception();
Object extraInfo = new Object();
publisher.publishAuthenticationFailure(new BadCredentialsException(""), a);
publisher.publishAuthenticationFailure(new BadCredentialsException("", cause), a);
verify(appPublisher, times(2)).publishEvent(isA(AuthenticationFailureBadCredentialsEvent.class));