You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring上下文环境下Vaadin CustomAuthenticationFailureHandler失效问题求助

解决方案

问题根源

你当前的配置同时使用了VaadinWebSecurity的setLoginView和手动配置的formLogin,两者存在冲突,导致Spring管理的CustomAuthenticationFailureHandler无法被正确加载生效;另外同时配置failureHandler和failureUrl也会引发逻辑冲突。

修复步骤

1. 调整SecurityConfig配置

移除手动的formLogin完整配置,保留VaadinWebSecurity的原生登录规则,仅通过Spring Security注册自定义失败处理器:

@EnableWebSecurity
@Configuration
public class SecurityConfig extends VaadinWebSecurity {

    private final AppUserRepository userRepository;
    private final CustomAuthenticationFailureHandler failureHandler;

    public SecurityConfig(AppUserRepository appUserRepository, CustomAuthenticationFailureHandler failureHandler) {
        this.userRepository = appUserRepository;
        this.failureHandler = failureHandler;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 静态资源放行配置
        http.authorizeHttpRequests(auth ->
                auth.requestMatchers(AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/images/*.png")).permitAll()
        );

        // 仅配置登录失败处理器,不覆盖Vaadin的登录页面规则
        http.formLogin(form -> form.failureHandler(failureHandler));

        // 其他配置保持不变
        http.logout(logout -> logout.permitAll())
            .exceptionHandling(e -> e.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")))
            .headers(headers -> headers.frameOptions(frame -> frame.disable()));

        // 必须最后调用父类配置,确保Vaadin安全规则生效
        super.configure(http);
        setLoginView(http, LoginView.class);
    }
}

2. 优化CustomAuthenticationFailureHandler的注入方式

保持@Service注解标记,改用构造器注入替代字段注入(更符合Spring最佳实践,避免上下文初始化依赖问题):

@Service
@Slf4j
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    private final LogService logService;

    // 构造器注入LogService
    public CustomAuthenticationFailureHandler(LogService logService) {
        this.logService = logService;
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        String username = request.getParameter("username");
        log.error("Wrong login: {}", username);
        logService.auditLog("UNKNOWN", LogTypes.SEC_ERR, "Wrong login: " + username);
        // 调用父类方法,确保默认的失败跳转逻辑正常执行
        super.onAuthenticationFailure(request, response, exception);
    }
}

3. 验证登录视图的错误展示逻辑

确保Vaadin的LoginView能正确识别登录失败的参数并展示错误:

@Route("login")
public class LoginView extends LoginOverlay {

    public LoginView() {
        setAction("login");
        setTitle("My App");
        setDescription("Please log in to continue");
        // 检查URL中的error参数,触发错误提示
        if (VaadinRequest.getCurrent().getParameter("error") != null) {
            setError(true);
        }
    }
}

关键注意事项

  • 不要同时使用VaadinWebSecurity的setLoginView和手动formLogin().loginPage(),二者配置会冲突,导致自定义处理器无法触发。
  • 确保LogService本身是Spring管理的Bean(如标记@Service或@Repository),否则会出现注入失败。

内容的提问来源于stack exchange,提问作者Ferenc Vilagi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 17:37:09