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

Vaadin 23首页设匿名访问后,跳转授权页面未重定向至Keycloak登录页

问题描述

原本所有Vaadin视图都使用@PermitAll注解,结合Spring Security + Keycloak配置正常,访问受保护页面会自动跳转到Keycloak登录页。将首页HomeView的注解改为@AnonymousAllowed后,匿名用户可正常访问首页,但点击其他带@PermitAll的视图(如DashboardView)时,系统显示路由找不到错误,而非跳转到Keycloak登录页。

相关关键信息:

  • 调试日志显示SpringViewAccessChecker拒绝访问受保护视图后,直接重定向到RouteNotFoundError页面
  • 所有受保护视图仍保留@PermitAll注解,SecurityConfig中OAuth2登录配置正常
原因分析

问题核心在于Vaadin视图访问检查与Spring Security的执行顺序:

  • Vaadin的SpringViewAccessChecker会优先处理视图上的权限注解(如@PermitAll),当检测到匿名用户访问受保护视图时,默认逻辑是将请求重定向到RouteNotFoundError,而非触发Spring Security的认证跳转流程。
  • 此时Spring Security没有机会拦截请求并执行登录重定向,因为Vaadin的路由检查已提前终止了请求处理。
解决方案

以下两种方式均可修复该问题:

方案一:通过Spring Security URL规则直接保护路由

在SecurityConfiguration的configure(HttpSecurity http)方法中添加URL级别的权限规则,让Spring Security优先拦截未认证请求并跳转到登录页:

@Override
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    // 添加URL权限规则,优先于Vaadin视图检查
    http.authorizeRequests()
            .antMatchers("/").permitAll() // 允许匿名访问首页
            .antMatchers("/dashboard", "/inbox", "/jobs", "/candidates", "/administration").authenticated(); // 其他路由需认证

    // 保留原有OAuth2和Logout配置
    http
            .oauth2Login(oauth2Login ->
                    oauth2Login
                            .clientRegistrationRepository(clientRegistrationRepository)
                            .userInfoEndpoint(userInfoEndpoint ->
                                    userInfoEndpoint
                                            .userAuthoritiesMapper(authoritiesMapper)
                            )
                            .successHandler(new VaadinSavedRequestAwareAuthenticationSuccessHandler())
            )
            .logout(logout ->
                    logout
                            .logoutSuccessHandler(logoutSuccessHandler())
                            .logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET"))
            );
}

此方式下,Spring Security会直接拦截未认证用户访问受保护URL的请求,跳转到Keycloak登录页,绕过Vaadin默认的错误处理逻辑。

方案二:自定义Vaadin访问检查逻辑,触发登录重定向

创建自定义BeforeEnterListener,在视图访问被拒绝时手动触发Spring Security的登录重定向:

@Component
public class CustomViewAccessChecker implements BeforeEnterListener {

    @Override
    public void beforeEnter(BeforeEnterEvent event) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 判断用户是否为未认证状态
        if (authentication == null || !authentication.isAuthenticated() || authentication instanceof AnonymousAuthenticationToken) {
            VaadinServletRequest request = VaadinServletRequest.getCurrent();
            if (request != null) {
                try {
                    // 触发Keycloak OAuth2登录重定向
                    String loginUrl = request.getHttpServletRequest().getContextPath() + "/oauth2/authorization/keycloak";
                    request.getHttpServletRequest().sendRedirect(loginUrl);
                    event.rerouteTo(HomeView.class); // 终止Vaadin路由处理
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

在MainLayout中注册该监听器:

@RouteLayout
public class MainLayout extends AppLayout {
    public MainLayout(CustomViewAccessChecker accessChecker) {
        addBeforeEnterListener(accessChecker);
        // 原有createDrawer等初始化代码
    }
}

此方式会在Vaadin路由检查前判断用户认证状态,未认证则直接触发登录重定向。

注意事项
  • 使用方案一时,需确保URL规则与Vaadin路由的value完全匹配(如DashboardView的@Route(value = "dashboard")对应URL/dashboard)
  • 两种方案均需保留原有的Spring Security与Keycloak配置,确保登录成功后能跳回原请求页面(依赖VaadinSavedRequestAwareAuthenticationSuccessHandler)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 22:27:33