春季不良信用事件未触发

2022-09-04 01:32:41

如果用户尝试使用错误的凭据进行身份验证,我想记录。因此,我已将此事件侦听器类添加到我的项目中:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.stereotype.Component;

@Component
public class AuthenticationFailureListener
        implements ApplicationListener<AuthenticationFailureBadCredentialsEvent>{

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) {
        System.out.println("test");
        logger.info("test2");
    }
}

问题是它根本不起作用。我使用Spring Security默认登录页面。使用错误的凭据时,页面显示“错误的凭据”错误,但我上面的方法不会被调用。我有一个非常相似的代码用于成功的事件侦听器,它工作得非常好:

@Component
public class AuthenticationSuccessListener implements
        ApplicationListener<InteractiveAuthenticationSuccessEvent> {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired private UserService users;

    @Override
    public void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
        User user = users.get(event.getAuthentication().getName());
        boolean isAdmin = user.getRole().equals(User.ROLE_ADMIN);
        logger.info((isAdmin ? "Admin" : "User") + " with id " + user.getIdLink()
                + " has successfully logged in!");
    }
}

这是我的Spring Security Java配置:

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{

    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .formLogin()
                .and()
            .httpBasic();
    }
}

我不知道这里发生了什么,帮助非常感谢!

Spring 版本:4.0.9
Spring Security 版本:3.2.5(也尝试过 4.0.1)


编辑:

好的,我将日志级别设置为Spredim的DEBUG,但什么都没有。我搜索了“侦听器”的每个出现,并且日志状态表明已经创建了身份验证FailureListener和身份验证成功列表器的实例,没有任何错误。

我甚至将日志放入diff工具(在替换所有时间和审查之后),并与代码版本进行比较,其中FailorListener代码被注释掉,但没有找到一些东西。如果您愿意,可以自己搜索:
https://www.diffchecker.com/cwdn4sp4
在页面底部,您将在左侧找到纯日志文本。


编辑2:部分解决

Serges解决方案有所帮助,以下是我对onAuthenticationFailure方法的完整实现:

@Override
public void onAuthenticationFailure(
        HttpServletRequest request, HttpServletResponse response,
        AuthenticationException exception) throws IOException, ServletException {

    if (exception instanceof BadCredentialsException) {
        String name = request.getParameter("username");
        String password = request.getParameter("password");
        Authentication auth =
                new UsernamePasswordAuthenticationToken(name, password);
        eventPublisher.publishEvent(
                new AuthenticationFailureBadCredentialsEvent(auth, exception));
    }
    super.onAuthenticationFailure(request, response, exception);
}

答案 1

我以不同的方式完成了这项工作。

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{

    // Inject applicationEventPublisher
    @Inject
    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            // configure a auth event publisher
            .authenticationEventPublisher(new DefaultAuthenticationEventPublisher(applicationEventPublisher))
            .userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .formLogin()
                .and()
            .httpBasic();
    }
}

通过这些更改,我的事件侦听器能够接收身份验证失败事件。这是与弹簧安全4.0.2.发布和弹簧启动1.2.5.释放

希望它有帮助。


答案 2

这是设计使然

Javadoc for 很清楚:AbstractAuthenticationProcessingFilter

活动刊登 :

如果身份验证成功,将通过应用程序上下文发布交互式身份验证成功事件。如果身份验证不成功,则不会发布任何事件,因为这通常通过特定于身份验证管理器的应用程序事件进行记录。

(强调我的)

如果要显式发送身份验证失败的事件,则可以使用自定义扩展来发送事件并调用基类方法。AuthenticationFailureHandlerSimpleUrlAuthenticationFailureHandleronAuthenticationFailure

public class EventSendingAuthenticationFailureHandler
        extends SimpleUrlAuthenticationFailureHandler,
        implements ApplicationEventPublisherAware {

    protected ApplicationEventPublisher eventPublisher;

    public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    @Override
    void onAuthenticationFailure(javax.servlet.http.HttpServletRequest request,
                       javax.servlet.http.HttpServletResponse response,
                       AuthenticationException exception)
                         throws IOException,
                                javax.servlet.ServletException {
        // use eventPublisher to publish the event according to exception
        super.onAuthenticationFailure(request, response, exception);
    }
}

您应该能够以这种方式配置它:

@Bean
AuthenticationFailureHandler eventAuthenticationFailureHandler() {
    return new EventSendingAuthenticationFailureHandler();
}

@Autowired
AuthenticationFailureHandler eventAuthenticationFailureHandler;

protected void configure(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .formLogin().failureHandler(eventAuthenticationFailureHandler)
            .and()
        .httpBasic();
}

推荐