跳至主要內容

处理认证失败后的逻辑AuthenticationFailureHandler

Jin大约 3 分钟

处理认证失败后的逻辑AuthenticationFailureHandler

1、简介

AuthenticationFailureHandler 是一个接口,用于处理认证失败后的逻辑。当用户尝试登录并提供无效的凭据时,AuthenticationFailureHandler 会处理认证失败的情况。可以自定义该处理器来执行特定的操作,如显示错误消息、记录登录失败信息、跳转到特定页面等。作用如下:

  • 提供详细的错误消息给用户。
  • 在认证失败时记录错误信息或进行其他操作。
  • 控制认证失败后的跳转页面或重定向。
  • 限制连续的登录失败次数(例如账户锁定机制)。

2、源码

public interface AuthenticationFailureHandler {
    void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException;
}

参数说明:

  • HttpServletRequest request:当前请求对象,用于获取请求的详细信息。
  • HttpServletResponse response:当前响应对象,用于发送响应信息。
  • AuthenticationException exception:认证失败时抛出的异常。这个异常包含了失败的原因,通常是 BadCredentialsException 或其他认证失败的异常。

3、使用场景

3.1、提示用户输入错误的凭据

最常见的场景是当用户输入错误的用户名或密码时,重定向到登录页面并显示错误信息。

public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        // 记录错误信息,可以在这里进行日志记录等
        request.setAttribute("error", "Invalid username or password"); // 设置错误消息到请求中

        // 重定向到登录页面,并显示错误提示
        request.getRequestDispatcher("/login?error=true").forward(request, response); // 转发到登录页面并附带错误标志
    }
}

此示例中,如果登录失败,将错误信息传递给登录页面,并将用户重定向回登录页面,通常是显示一个“错误”的标识,提示用户凭据输入错误

3.2、记录失败日志

ublic class LoggingAuthenticationFailureHandler implements AuthenticationFailureHandler {

    private static final Logger logger = Logger.getLogger(LoggingAuthenticationFailureHandler.class.getName());

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        String username = request.getParameter("username");
        
        // 记录登录失败的日志
        logger.warning("Login attempt failed for user: " + username);

        // 跳转回登录页面并提示错误
        response.sendRedirect("/login?error=true");
    }
}

3.3、登录失败次数限制(账户锁定)

public class FailureCountAuthenticationFailureHandler implements AuthenticationFailureHandler {

    private static final int MAX_FAILURES = 5; // 最大失败次数
    private static final AtomicInteger failureCount = new AtomicInteger(0); // 记录失败次数

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        // 增加失败次数
        failureCount.incrementAndGet();

        if (failureCount.get() >= MAX_FAILURES) {
            // 达到最大失败次数,锁定账户或进行其他操作
            response.sendRedirect("/account-locked"); // 跳转到账户锁定页面
        } else {
            // 否则继续提示错误
            response.sendRedirect("/login?error=true");
        }
    }
}

4、配置

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
//                开启授权保护
                .authorizeHttpRequests(authorize -> authorize
                        .anyRequest()//对所有请求开启授权保护
                        .authenticated()//已认证的请求会被自动授权
                )
                //自定义登录页面
                .formLogin(form -> form.loginPage("/login").permitAll()
                        .successHandler(new MyAuthenticationSuccessHandler()) //认证成功时的处理
                        .failureHandler(new MyAuthenticationFailureHandler()) //认证失败时的处理
                )//.permitAll() 解决localhost 将您重定向的次数过多
                .httpBasic(withDefaults())//使用基本授权方式
                .csrf(AbstractHttpConfigurer::disable)//关闭 csrf 攻击防御

        ;
        return http.build();
    }

贡献者: Jin