当前位置: 首页 > 知识库问答 >
问题:

Spring Bad凭据事件不触发

殳睿
2023-03-14

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

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)

编辑:

好的,我将Spring的日志级别设置为DEBUG,但没有。我搜索了“侦听器”的每次出现,日志指出已经创建了身份验证失败侦听器和身份验证成功侦听器的实例,没有任何错误。

我甚至把日志放进了diff工具(在每次更换之后

Edit2:部分解决

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);
}

共有3个答案

周和志
2023-03-14

LoggerListener在Spring Security 3.2.8中运行良好。源代码见Grepcode。

您的adpoted代码:

@Named
public class AuthenticationSuccessListener implements ApplicationListener<AbstractAuthenticationEvent> {

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

    @Inject
    private UserService users;

    @Override
    public void onApplicationEvent(AbstractAuthenticationEvent event) {

        if (event instanceof InteractiveAuthenticationSuccessEvent) {

            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!");
        }
    }
}
夏弘义
2023-03-14

这是故意的。

AbstractAuthenticationProcessingFilter的Javadoc很清楚:

事件发布:

如果身份验证成功,将通过应用程序上下文发布InteractiveAuthenticationSuccessEvent。如果身份验证失败,则不会发布任何事件,因为这通常会通过AuthenticationManager特定的应用程序事件进行记录。

(强调我的)

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

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();
}
壤驷鸿
2023-03-14

我用另一种方式工作。

@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();
    }
}

通过这些更改,我的事件侦听器能够接收身份验证失败事件。这是spring-Security 4.0.2。RELEASE和spring-boot 1.2.5。释放

希望有帮助。

 类似资料:
  • 使用mui.trigger()方法可以动态触发特定DOM元素上的事件。 .trigger( element , event , data ) element Type: Element 触发事件的DOM元素 event Type: String 事件名字,例如:'tap'、'swipeleft' data Type: Object 需要传递给事件的业务参数 示例 自动触发按钮的点击事件: var

  • 我正在使用Amazon Transcripbe服务,并试图让CloudWatch事件激发一个Lambda函数,该函数执行对我的API的POST请求。 下面是Lambda函数 我已经将CloudWatch事件配置为监听Amazon Transcripbe服务,特别是监听作业状态更改为或。 这是我认为我的应用程序工作的唯一方式,转录作业是通过亚马逊转录服务调用的,然后当它完成时,点击我的API来更新我

  • 问题内容: 我的整个项目都使用(Bluebird)Promises,但是有一个使用EventEmitter的特定库。 我想要实现以下目标: 我在Promises链中读了EventEmitter的答案。这给了我一种执行’connect’事件的回调的方法。这是我到目前为止所到之处 现在如何进一步链接“ eventB”? 问题答案: 我假设您想为每个事件做不同的事情。即使由的动作触发,您也可以将其视为另

  • 触摸操作概述 浏览器的触摸 API 由三个部分组成。 Touch:一个触摸点 TouchList:多个触摸点的集合 TouchEvent:触摸引发的事件实例 Touch接口的实例对象用来表示触摸点(一根手指或者一根触摸笔),包括位置、大小、形状、压力、目标元素等属性。有时,触摸动作由多个触摸点(多根手指)组成,多个触摸点的集合由TouchList接口的实例对象表示。TouchEvent接口的实例对

  • 问题内容: 我从android.app.Application派生了一个自定义应用程序,但无法触发它的onCreate事件。这是实现 这是我的使用方式: 问题答案: 在您的中添加以下内容 然后你会被解雇。

  • 问题内容: 我有3个文件: js_json.js->用于我的json代码 javascript.js->用于我的javascript函数 index.php 这里的代码为: 这是我的代码: 这里的代码: 我的问题是: 当我单击链接“ Hola Test 1”时,它将起作用并显示消息。问题是,在单击选择选项之后,出现了链接“ Hola Test”,然后单击该链接(“ Hola Test”),该消息没