在每次请求时发布Spring Security Oauth2 AuthenticationSuccessEvent [英] Spring Security Oauth2 AuthenticationSuccessEvent published at each request

查看:1279
本文介绍了在每次请求时发布Spring Security Oauth2 AuthenticationSuccessEvent的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using Spring Security Oauth2 to secure my Spring Boot REST app. I want to process some operation after a user login success and failure. The problem is each time I send a request with the user bearer token, AuthenticationSuccessEvent is published even the user is already authenticated.

此处理程序始终称为:

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

正常吗?我希望它被调用一次.

Is it normal? I want it to be called once.

感谢您的帮助

推荐答案

默认情况下(从Spring 5.x开始)在每个令牌/refresh_token上调用 AuthenticationSuccessEvent 事件的原因是授权:基本clientID:clientSecret" 标头作为令牌请求的一部分出现,因此由 BasicAuthenticationFilter 处理的请求以及使用相应的 AuthenticationManager(ProviderManager)对客户端进行身份验证的(除了负责令牌身份验证的 ProviderManager 之外).

The reason that AuthenticationSuccessEvent event is being called on every token/refresh_token by default (starting from Spring 5.x) is because "Authorization: Basic clientID:clientSecret" header is presented as part of token request thus request handled by BasicAuthenticationFilter as well that authenticates the client using corresponding AuthenticationManager(ProviderManager) (in addition to the ProviderManager that is responsible for the token auth) implementation.

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

Each ProviderManager, in turn, has AuthenticationEventPublisher dependency that is used for publishing different kinds of events, in our case(auth success), it is eventPublisher.publishAuthenticationSuccess(result);

默认情况下, ProviderManager 使用 NullEventPublisher ,可以使用 ProviderManager#setAuthenticationEventPublisher 设置器来覆盖它.

By default ProviderManager uses NullEventPublisher that could be overridden using ProviderManager#setAuthenticationEventPublisher setter.

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

ProviderManager is created by 'AuthenticationManagerBuilder that set corresponding event publisher to it(if not 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中添加):

AuthenticationManagerBuilder is populated from WebSecurityConfigurerAdapter see WebSecurityConfigurerAdapter#getHttp method where you cand find the following line(that was added in Spring Security 5.x):

authenticationBuilder.authenticationEventPublisher(eventPublisher);

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

One of the approaches to override that default behavior is to implement corresponding BasicWebSecurityConfig(extending WebSecurityConfigurerAdapter or AuthorizationServerSecurityConfiguration) and set NullEventPublisher to the 'AuthenticationManagerBuilder before ProviderManager creation:

@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) {
    }
}
}

这篇关于在每次请求时发布Spring Security Oauth2 AuthenticationSuccessEvent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆