Vaadin 24整合Spring Security配置时出现无效JSON响应及路由导航异常
Vaadin 24整合Spring Security配置时出现无效JSON响应及路由导航异常
从你提供的信息和Debug日志来看,问题的核心出在登录请求参数不匹配和Vaadin视图访问控制配置冲突上,我来一步步帮你梳理解决:
一、先解决「Invalid JSON响应」的问题
从日志里的Failed to find user ''可以看出,Spring Security收到了一个空的用户名,导致认证失败后触发了重定向(跳转到/?error),而Vaadin前端此时正在等待JSON格式的UIDL响应,收到HTML重定向内容就会抛出无效JSON的错误。
解决步骤:
检查你的LoginView表单字段
确保登录表单的用户名、密码输入框的name属性严格对应Spring Security的默认参数名:username和password。比如:@Route("login") @AnonymousAllowed // 必须加这个,让未登录用户能访问登录页 public class LoginView extends VerticalLayout { public LoginView() { TextField usernameField = new TextField("用户名"); usernameField.setName("username"); // 关键:name属性不能错 usernameField.setAutofocus(true); PasswordField passwordField = new PasswordField("密码"); passwordField.setName("password"); // 同上 Button loginBtn = new Button("登录", e -> { // 用Vaadin的认证机制处理,避免Spring Security的默认重定向 Authentication auth = UsernamePasswordAuthenticationToken.unauthenticated( usernameField.getValue(), passwordField.getValue() ); try { auth = SecurityContextHolder.getContext().getAuthenticationManager().authenticate(auth); SecurityContextHolder.getContext().setAuthentication(auth); // 登录成功后跳转到主视图 UI.getCurrent().navigate(MainView.class); } catch (AuthenticationException ex) { Notification.show("登录失败:" + ex.getMessage(), 3000, Notification.Position.TOP_CENTER); } }); add(usernameField, passwordField, loginBtn); setSizeFull(); setAlignItems(Alignment.CENTER); setJustifyContentMode(JustifyContentMode.CENTER); } }修正SecurityConfig的登录视图配置
确保setLoginView指向正确的LoginView,同时提前开放静态资源的访问权限:@EnableWebSecurity @Configuration public class SecurityConfig extends VaadinWebSecurity { @Override protected void configure(HttpSecurity http) throws Exception { // 先开放Vaadin静态资源,避免被拦截 http.authorizeHttpRequests() .requestMatchers(new AntPathRequestMatcher("/VAADIN/**"), new AntPathRequestMatcher("/themes/**")) .permitAll(); super.configure(http); // 正确绑定登录视图 setLoginView(http, LoginView.class); } @Override public void configure(WebSecurity web) throws Exception { // 让Spring Security忽略Vaadin的内部请求 web.ignoring().requestMatchers( new AntPathRequestMatcher("/VAADIN/**"), new AntPathRequestMatcher("/themes/**"), new AntPathRequestMatcher("/favicon.ico") ); super.configure(web); } @Bean public UserDetailsManager userDetailsService() { UserDetails user = User.withUsername("user") .password("{noop}user") .roles("USER") .build(); UserDetails admin = User.withUsername("admin") .password("{noop}admin") .roles("ADMIN") .build(); return new InMemoryUserDetailsManager(user, admin); } }
二、解决「路由导航异常」的问题
当你注释掉setLoginView后,Vaadin的视图访问检查器没有正确生效,导致所有路由都被拦截。解决要点:
给需要授权访问的视图添加权限注解
比如主视图MainView:@Route("main") @RolesAllowed({"USER", "ADMIN"}) // 允许普通用户和管理员访问 public class MainView extends VerticalLayout { // ... 视图代码 }注册页、登录页这类允许匿名访问的页面,必须添加
@AnonymousAllowed注解。不要手动覆盖VaadinWebSecurity的核心配置
VaadinWebSecurity已经帮你处理了CSRF保护、视图访问检查、请求缓存等适配Vaadin的配置,不要手动添加http.formLogin()这类原生Spring Security配置,否则会和Vaadin的机制冲突。
额外注意事项
- 不要使用Spring Security的默认登录端点(
/login),而是用Vaadin自己的LoginView处理登录,避免重定向导致的JSON响应错误。 - 确保你的Vaadin版本(24.0.3)和Spring Boot版本(3.0.5)兼容,这两个版本的搭配是没问题的,但要注意依赖的一致性。
备注:内容来源于stack exchange,提问作者Jmork
相关产品推荐
相关产品推荐

