You need to enable JavaScript to run this app. Angular对接带JWT的Spring Boot服务PUT请求403跨域预检失败排查
优惠活动
大模型
产品
解决方案
定价
更多

Angular对接带JWT的Spring Boot服务PUT请求403跨域预检失败排查

核心问题诱因
  • 配置逻辑存在低级断层:写了完整的跨域规则参数后,路由注册环节根本没有使用这份配置——代码重新实例化了一个空白的CorsConfiguration对象,靠默认值生成规则,默认规则仅放行GET、HEAD、POST三类请求,完全不包含PUT、OPTIONS的权限,前面写的配置全部无效。
  • 规则与浏览器规范不匹配:开启setAllowCredentials(true)时,浏览器CORS机制不支持*作为通配源,即便配置了全源放行规则,浏览器也会判定响应无效,不会通过跨域校验。
  • 安全拦截链路存在缺口:Spring Security的授权规则没有对OPTIONS类型的预检请求做放行配置,这类请求不会携带JWT鉴权头,会被后续的认证过滤器拦截返回401状态,响应中自然不会携带要求的Access-Control-Allow-Origin头,直接触发浏览器的CORS阻断报错。

补充说明:GET、POST请求未触发异常,是因为不带自定义请求头的简单请求不会触发浏览器的OPTIONS预检流程,可直接通过链路访问;PUT请求因携带JWT相关的自定义请求头,属于非简单请求,必须先完成预检校验,因此会暴露上述配置问题。

调整修复方案
  • 修正配置传递逻辑:将自定义的跨域配置实例传入UrlBasedCorsConfigurationSource的注册方法,不再使用无意义的默认空配置。
  • 匹配凭证模式下的源规则:替换*通配源,明确写入需要放行的前端源地址(包含本地开发地址、正式部署后的前端地址)。
  • 补充预检请求放行规则:在Spring Security的授权链路中,显式允许所有路径下的OPTIONS请求直接通过,不经过JWT鉴权拦截。
  • 补齐请求头放行范围:显式配置允许跨域携带的请求头,覆盖JWT认证需要的Authorization头。
修正后的关键配置代码
@Bean
CorsConfigurationSource configurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    // 替换*通配源,匹配allowCredentials的浏览器规范要求
    configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
    configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH", "OPTIONS"));
    // 显式放行所有请求头,覆盖JWT认证需要的Authorization头
    configuration.setAllowedHeaders(Arrays.asList("*"));
    configuration.setAllowCredentials(true);
    // 配置预检缓存时长,减少重复预检请求开销
    configuration.setMaxAge(3600L);

    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    // 修正注册逻辑,传入已配置好的规则实例
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().configurationSource(configurationSource())
        .and()
        .csrf().disable()
        .authorizeRequests()
        // 新增规则:放行所有路径下的OPTIONS预检请求
        .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
        .antMatchers(AUTH_WHITELIST).permitAll()
        .antMatchers(HttpMethod.POST, "/authenticate/signup").permitAll()
        .anyRequest().authenticated()
        .and()
        .exceptionHandling().authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
        .and()
        .addFilter(new AuthenticationFilter(authenticationManager()))
        .addFilter(new AuthorizationFilter(authenticationManager()))
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .formLogin().usernameParameter("email");
}

配置生效后可先通过浏览器开发者工具的网络面板,查看PUT请求触发的OPTIONS预检响应是否正常携带Access-Control-Allow-Origin、Access-Control-Allow-Methods头,确认校验通过后,后续的正式PUT请求即可正常携带JWT完成鉴权交互。

内容的提问来源于stack exchange,提问作者Sabeeh Ul Haq

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.09 17:06:04