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

Vaadin 21中@RolesAllowed权限拦截后跳转自定义错误页问题

Vaadin 21处理@RolesAllowed权限不足的自定义重定向方案

问题原因

当用户已登录但无对应角色访问带@RolesAllowed注解的Vaadin路由时,Vaadin自身的路由访问控制会先拦截请求并抛出AccessDeniedException。这个异常发生在Vaadin客户端导航流程中,不会触发Spring Security的AccessDeniedHandler或accessDeniedPage配置(未走传统Servlet请求重定向逻辑),因此会出现Vaadin默认的导航错误空白页。

解决方案:使用Vaadin NavigationErrorHandler处理导航异常

Vaadin提供NavigationErrorHandler接口,专门捕获路由导航过程中的异常,可通过实现该接口处理权限不足场景,并重定向到自定义错误页。

步骤1:创建自定义权限不足页面

先实现一个无需权限访问的AccessDeniedView作为错误页:

@Route("accessDenied")
public class AccessDeniedView extends VerticalLayout {
    public AccessDeniedView() {
        setSizeFull();
        setAlignItems(Alignment.CENTER);
        setJustifyContentMode(JustifyContentMode.CENTER);
        
        add(new H1("权限不足"));
        add(new Paragraph("您没有访问该页面的权限,请联系管理员。"));
        add(new Button("返回首页", event -> UI.getCurrent().navigate("")));
    }
}

步骤2:实现自定义NavigationErrorHandler

创建Spring Bean实现NavigationErrorHandler接口,捕获AccessDeniedException并导航到错误页:

@Component
public class CustomNavigationErrorHandler implements NavigationErrorHandler {

    @Override
    public void handleNavigationError(Exception exception, RouterLocation location, UiContext uiContext) {
        if (exception instanceof AccessDeniedException) {
            // 导航到自定义权限不足页面
            uiContext.getUI().ifPresent(ui -> ui.navigate("accessDenied"));
        } else {
            // 其他导航异常交给默认处理器处理
            DefaultNavigationErrorHandler defaultHandler = new DefaultNavigationErrorHandler();
            defaultHandler.handleNavigationError(exception, location, uiContext);
        }
    }
}

步骤3:配置Security允许访问错误页

在继承VaadinWebSecurityConfigurerAdapter的配置类中,确保/accessDenied路由允许访问:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true) // 开启@RolesAllowed注解支持
public class SecurityConfig extends VaadinWebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        // 设置登录页
        setLoginView(http, LoginView.class);
        
        // 允许所有用户访问权限不足错误页
        http.authorizeRequests()
                .antMatchers("/accessDenied").permitAll();
    }
}

补充说明

  • 必须添加@EnableGlobalMethodSecurity(jsr250Enabled = true)才能让@RolesAllowed注解生效。
  • 该方案是Vaadin单页应用的最佳实践,基于客户端导航实现,无页面刷新,体验更流畅。
  • 若需兼容非Vaadin请求的权限处理,可同时配置Spring Security的AccessDeniedHandler,但Vaadin路由导航场景下,NavigationErrorHandler是核心解决方式。

内容的提问来源于stack exchange,提问作者Robyn.D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 13:35:33