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

Vaadin Spring Boot中Post请求遭CORS拦截问题求助

Vaadin Spring Boot中Post请求CORS报错问题

我在Vaadin Java Spring Boot应用里搭建了REST控制器,所有@GetMapping接口均可正常运行,但@PostMapping接口从Angular端调用时始终报CORS错误:

Access to XMLHttpRequest at <my_page> from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource。

从零新建普通Spring Boot应用时Post请求功能正常,但当前Vaadin应用中调整SecurityConfig和WebConfig参数后仍无法解决。相关代码如下:

REST控制器代码

@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*") // Allow requests from any origin
public class RESTController {
    

    @GetMapping("/hello")
    public String sayHello() {
        return "hello";
    }

    @PostMapping("/print")
    public Map<String, Object> printMessage(@RequestBody Map<String, Object> payload) {
        System.out.println("Received JSON: " + payload);
        payload.put("status", "Received successfully");
        return payload;
    }
}

SecurityConfiguration代码

@EnableWebSecurity
@Configuration
public class SecurityConfiguration
        extends VaadinWebSecurity  {

    @Autowired
    CrmService crmService;


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        
        http.authorizeHttpRequests(auth -> auth.requestMatchers(
                        new AntPathRequestMatcher("/jobs/images/**"), // Allow public access to images
                        new AntPathRequestMatcher("/api/getfields/**"), // Allow public access to /api/getfields/**
                        new AntPathRequestMatcher("/api/**"),
                        new AntPathRequestMatcher("/images/*.jpg"),
                        new AntPathRequestMatcher("/**/*.png"),
                        new AntPathRequestMatcher("/**/*.jpg"),
                        new AntPathRequestMatcher("/**/*.svg"),
                        new AntPathRequestMatcher("/**/*.css"),
                        new AntPathRequestMatcher("/**/*.ts"),
                        new AntPathRequestMatcher("/**/*.js"),
                        new AntPathRequestMatcher("/**/*.html")
                )
                .permitAll());
        
        setLoginView(http, LoginView.class);

        http.headers(headers -> headers
                .contentSecurityPolicy(csp -> csp
                        .policyDirectives("frame-ancestors 'self'")
                )
        );
        super.configure(http);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {

        // Customize your WebSecurity configuration.
        super.configure(web);
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new CustomUserDetailsService(crmService);
    }

}

WebConfig代码

@Configuration
public class WebConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**")
                        .allowedOrigins("*")
                        .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                        .allowedHeaders("*")
                        .maxAge(3600);

                registry.addMapping("/api/getfields/**")
                        .allowedOrigins("*")
                        .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                        .allowedHeaders("*")
                        .maxAge(3600);

            }
        };
    }
}

解决方案

问题核心在于Vaadin Security的规则优先级、OPTIONS预检请求被拦截,以及CORS配置的冲突,按以下步骤调整:

  1. 在SecurityConfig中放行OPTIONS请求并禁用API的CSRF
    跨域Post请求会先发送OPTIONS预检请求,必须确保该请求不被拦截;同时REST接口不需要CSRF保护,可直接忽略:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 禁用API路径的CSRF
        http.csrf(csrf -> csrf.ignoringRequestMatchers("/api/**"));
        
        // 先放行所有OPTIONS请求,再处理其他规则
        http.authorizeHttpRequests(auth -> auth
                .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .requestMatchers(
                    new AntPathRequestMatcher("/jobs/images/**"),
                    new AntPathRequestMatcher("/api/**"),
                    new AntPathRequestMatcher("/images/*.jpg"),
                    new AntPathRequestMatcher("/**/*.png"),
                    new AntPathRequestMatcher("/**/*.jpg"),
                    new AntPathRequestMatcher("/**/*.svg"),
                    new AntPathRequestMatcher("/**/*.css"),
                    new AntPathRequestMatcher("/**/*.ts"),
                    new AntPathRequestMatcher("/**/*.js"),
                    new AntPathRequestMatcher("/**/*.html")
                ).permitAll());
        
        setLoginView(http, LoginView.class);
    
        http.headers(headers -> headers
                .contentSecurityPolicy(csp -> csp
                        .policyDirectives("frame-ancestors 'self'")
                )
        );
        // 自定义规则要放在super.configure之前,避免被覆盖
        super.configure(http);
    }
    
  2. 简化CORS配置,避免重复冲突
    移除REST控制器上的@CrossOrigin注解,用全局配置统一处理,同时建议指定具体Origin而非通配符(生产环境更安全):

    @Configuration
    public class WebConfig {
        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurer() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/api/**")
                            .allowedOrigins("http://localhost:4200")
                            .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                            .allowedHeaders("*")
                            .allowCredentials(true) // 若需要携带Cookie则开启
                            .maxAge(3600);
                }
            };
        }
    }
    
  3. 验证调试
    重启应用后,打开浏览器开发者工具的Network面板,查看OPTIONS请求的响应头,确认Access-Control-Allow-Origin、Access-Control-Allow-Methods等关键头是否正确返回。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 19:19:57