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

Vaadin24+SpringBoot3/SpringSecurity6下POST请求参数丢失求助

问题分析与解决方案

问题背景

从Vaadin 14升级至24,同步完成Spring Boot 2→3、Spring Security 5→6的升级后,带有@AnonymousAllowed注解的路由接收x-www-form-urlencoded格式的POST请求时出现参数丢失问题。日志显示POST请求已到达应用,payload中包含payRequest参数及对应JSON结构,但后续请求自动转为无参数的GET请求,最终Vaadin视图无法获取到payRequest参数。该功能在Vaadin 14中可正常运行。

核心原因

Vaadin 20+版本的路由机制发生变更:当POST请求直接访问Vaadin路由时,框架会先完成POST请求的基础处理,随后触发UI初始化的GET重定向(即日志中出现的GET /?v-r=init&location=payments-list%2Fexternal-api&query=),这个重定向过程默认不会携带原POST请求的参数。而Vaadin 14不存在该自动重定向逻辑,POST参数可直接传递到视图。

解决方案

方案1:通过Spring MVC端点中转POST参数

创建独立的Spring MVC控制器接收POST请求,将参数存入Session后重定向到Vaadin路由,最后在视图中从Session取出参数:

@Controller
@RequestMapping("/payments-list")
public class PaymentPostController {

    @PostMapping("/external-api")
    public String handlePost(@RequestParam("payRequest") String payRequest, HttpSession session) {
        session.setAttribute("payRequest", payRequest);
        return "redirect:/payments-list/external-api";
    }
}

在Vaadin视图的afterNavigation方法中读取参数:

@Override
public void afterNavigation(AfterNavigationEvent event) {
    String payRequest = (String) VaadinSession.getCurrent().getAttribute("payRequest");
    if (payRequest != null) {
        // 执行业务逻辑处理参数
        VaadinSession.getCurrent().removeAttribute("payRequest"); // 用完清理Session,避免重复读取
    }
}

方案2:自定义Vaadin RequestHandler处理POST参数

自定义RequestHandler拦截POST到目标路由的请求,将参数存入请求属性,供后续UI初始化使用:

@Component
public class PostParameterForwardHandler extends AbstractRequestHandler {

    @Override
    public boolean handleRequest(VaadinRequest request, VaadinResponse response) throws IOException {
        if ("POST".equals(request.getMethod()) && request.getPathInfo().contains("/payments-list/external-api")) {
            String payRequest = request.getParameter("payRequest");
            if (payRequest != null) {
                request.setAttribute("payRequest", payRequest);
            }
        }
        return false; // 放行让后续Vaadin处理逻辑继续执行
    }
}

在Vaadin视图中读取参数:

@Override
public void afterNavigation(AfterNavigationEvent event) {
    String payRequest = (String) VaadinRequest.getCurrent().getAttribute("payRequest");
    // 执行业务逻辑
}

方案3:调整Spring Security配置确保参数传递

检查Spring Security 6的过滤器链配置,确保POST请求参数不会被过滤或拦截:

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/payments-list/external-api").permitAll()
                .anyRequest().authenticated()
            )
            // 如果外部请求无法携带CSRF令牌,可忽略该端点的CSRF校验
            .csrf(csrf -> csrf.ignoringRequestMatchers("/payments-list/external-api"));
        return http.build();
    }
}

验证建议

  • 在中转端点或自定义RequestHandler中添加日志,确认参数被正确接收
  • 在Vaadin视图中打印Session或请求属性,验证参数可被正常读取

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:24:55