Spring Security:AuthenticationFailureCredentialsExpiredEvent未被触发

时间:2013-02-13 16:08:39

标签: spring spring-security

我使用的是spring.security.version = 3.1.0.RELEASE。我遇到的问题是由于某种原因,不会触发AuthenticationFailureCredentialsExpiredEvent。

在调试代码时,我发现AbstractUserDetailsAuthenticationProvider确实在控制台中显示“用户帐户凭据已过期”。但我仍然感到困惑的是为什么没有触发关注的事件。

这是我的代码:

class JpaUserDetails implements UserDetails {
...
...
   @Override
   public boolean isCredentialsNonExpired() {
       if (some logic) {
           return true;
       }
       else {
           return false;
       }
   }
}

我确实看到AbstractUserDetailsAuthenticationProvider在控制台“用户帐户凭据已过期”中显示以下几行代码:

public abstract class AbstractUserDetailsAuthenticationProvider implements AuthenticationProvider, InitilizeBean, MessageSourceAware {
...
...
    private class DefaultPostAuthenticationChecks implements UserDetailsChecker {
        public void check(UserDetails user) {
            if(!user.isCredentialsNonExpired()) {
                logger.debug("User account credentials have expired");
                throw new CredentialsExpiredException(message.getMessage(
                          "AbstractUserDetailsAuthenticationProvider.credentialsExpired",
                          "User credentials have expired"), user);
            }
        }
    }
}

问题是,当用户凭据已过期时,我希望Spring生成我正在以下列方式处理的事件AuthenticationFailureCredentialsExpiredEvent:

class SecurityEventDispatcher implements ApplicationListener<ApplicationEvent> {
    final List<SecurityEventListener> listeners = new ArrayList<SecurityEventListener>();

    public void registerListener(SecurityEventListener listener) {
        this.listener.add(listener);
    }

    public void onApplicationEvent(ApplicationEvent event) {
        for (SecurityEventListener listener : this.listeners) {
            if(listener.canHandle(event)) {
                listener.handle(event);
            }
        }
    }
}

这就是我处理登录失败事件的方式:

public class LoginFailedEvent extends SecurityEventListener {

    @Override
    public boolean canHandle(Object event) {
        if(event instanceof AbstractAuthenticationFailureEvent) {
            return true;
        }
        else {
            return false;
        }
    }

    @Override
    public void handle(Object event) {
        if (event instanceof AuthenticationFailureBadCredentialsEvent) {
            // do something
        }

        if (event instanceof AuthenticationFailureCredentialsExpiredEvent) {
            // do something
        }
    }
}

我之前提到的问题是从不触发AuthenticationFailureCredentialsExpiredEvent。我已经测试了AuthenticationFailureBadCredentialsEvent,它可以正常工作。

这是因为凭据不良而得到的结果:(工作正常)

  

org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent

这是我在密码过期时遇到的情况:

  带有failureCause = null的

ServletRequestHandledEvent:url = [/ app / loginFailure]

有谁知道可能出现什么问题?任何帮助将受到高度赞赏。

2 个答案:

答案 0 :(得分:1)

以下是这个问题的答案,因为关于这个问题的文献不多。

  

您可能需要设置ProviderManager   ('s)eventPublisher不是   NullEventPublisher。没有一种简单的方法可以通过    标签,所以你会想要创建   AuthenticationProvider使用标准bean配置和注入   它成为ProviderManager的标准Spring Bean。

     

Rob Winch - 春季安全负责人

答案 1 :(得分:0)

如果有人遇到此问题,只需将弹簧安全性升级到3.1.2或+,问题就解决了。