Spring Security Oauth2 AuthenticationSuccessEvent在每个请求中发布

时间:2018-06-03 04:57:50

标签: spring-boot authentication spring-security spring-security-oauth2

我正在使用Spring Security Oauth2来保护我的Spring Boot REST应用程序。我想在用户登录成功和失败后处理一些操作。问题是每一个  时间我发送带有用户承载令牌的请求,即使用户已经过身份验证,也会发布AuthenticationSuccessEvent

始终调用此处理程序:

@Async
@EventListener( { AuthenticationSuccessEvent.class } )
public void listenAuthenticationSuccessEvent( AuthenticationSuccessEvent event ) {
    AbstractAuthenticationToken auth = (AbstractAuthenticationToken) event
            .getSource();
    log.info( "User connected: {}", auth.getName() );
}

这是正常的吗?我希望它被召唤一次。

寻求帮助

1 个答案:

答案 0 :(得分:1)

默认情况下(从Spring 5.x开始)在每个令牌/ refresh_token上调用 AuthenticationSuccessEvent 事件的原因是“授权:基本的clientID:clientSecret” 标头作为令牌请求的一部分出现,因此由 BasicAuthenticationFilter 处理的请求以及使用相应的 AuthenticationManager(ProviderManager)(除了 ProviderManager em>负责令牌auth)的实现。

每个 ProviderManager 依次具有 AuthenticationEventPublisher 依赖性,该依赖性用于发布各种事件,在我们的案例中(验证成功),它是 eventPublisher .publishAuthenticationSuccess(result);

默认情况下, ProviderManager 使用 NullEventPublisher ,可以使用 ProviderManager#setAuthenticationEventPublisher setter覆盖。

ProviderManager 'AuthenticationManagerBuilder 创建,并为其设置了相应的事件发布者(如果不为null)。

protected ProviderManager performBuild() throws Exception {
...
ProviderManager providerManager = new ProviderManager(authenticationProviders,
        parentAuthenticationManager);
...
if (eventPublisher != null) {
   providerManager.setAuthenticationEventPublisher(eventPublisher);
}

AuthenticationManagerBuilder是从 WebSecurityConfigurerAdapter 填充的,请参见 WebSecurityConfigurerAdapter#getHttp 方法,您可以在其中找到以下行(在Spring Security 5.x中添加):

authenticationBuilder.authenticationEventPublisher(eventPublisher);

覆盖默认行为的一种方法是实现相应的BasicWebSecurityConfig(扩展WebSecurityConfigurerAdapter或AuthorizationServerSecurityConfiguration),并在创建 ProviderManager 之前将NullEventPublisher设置为'AuthenticationManagerBuilder

@Configuration
@Order(-1)
public class BasicSecurityConfiguration extends AuthorizationServerSecurityConfiguration {
@Override
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);

    // override default DefaultAuthenticationEventPublisher to avoid excessive firing of
    // AuthenticationSuccessEvent on successful client credentials verification that passed in "Authorization: Basic clientId:clientSecret" header
    http.getSharedObject(AuthenticationManagerBuilder.class).authenticationEventPublisher(new NullEventPublisher());
    http.httpBasic()
}

private static final class NullEventPublisher implements AuthenticationEventPublisher {
    public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) {
    }

    public void publishAuthenticationSuccess(Authentication authentication) {
    }
}
}