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

React向Spring Boot后端请求时自定义Header丢失问题求助

我来帮你拆解并解决这个问题,你遇到的是典型的CORS预检请求(OPTIONS)处理不当导致的问题,咱们一步步来梳理:

首先纠正前端的两个关键错误

  1. Access-Control-Allow-Origin是响应头,不是请求头!
    你在fetch和axios里给请求加这个头完全没必要,反而会触发浏览器更严格的预检机制——因为自定义请求头会强制浏览器先发送OPTIONS预检请求,这也是后续问题的导火索之一,直接删掉这行配置。

  2. Authorization头格式错误
    你写的'Bearer' + token少了一个空格,正确格式应该是'Bearer ' + token(Bearer后面必须跟空格),否则后端解析令牌时会失败。

修改后的代码如下:

Fetch版本

fetch('http://127.0.0.1:8080/api/tender', {
  method: 'GET',
  headers: { 
    Authorization: 'Bearer ' + token
  }
});

Axios版本

axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
// 删掉这行:axios.defaults.headers.common['Access-Control-Allow-Origin'] = '*';
axios.get('http://127.0.0.1:8080/api/tender').then((res) => console.log(res));

后端Spring Boot的核心配置调整

浏览器发送OPTIONS预检请求时,不会携带Authorization头(这是浏览器的安全机制),所以你的后端必须对OPTIONS请求放行,不能做令牌验证,否则预检失败后,后续的GET请求根本不会被触发。

方案1:全局CORS配置

添加全局CORS配置类,明确允许前端域名、请求方法和自定义请求头:

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOrigins("http://localhost:3000")  // 明确指定你的前端域名,不要用*(带认证场景下*不生效)
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("Authorization", "Content-Type")  // 允许Authorization请求头
                .allowCredentials(true)  // 如果前端需要携带cookie,开启这个
                .maxAge(3600);  // 预检请求缓存时长,减少OPTIONS请求次数
    }
}

方案2:如果用Spring Security,还要额外放行OPTIONS请求

如果你的项目集成了Spring Security,需要在安全配置里单独允许OPTIONS请求通过,不做认证校验:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()  // 放行OPTIONS请求
            .anyRequest().authenticated();
        // 其他安全配置...
    }
}

为什么手动重发请求能成功?

手动重发GET请求时,浏览器不会触发预检流程(直接发送GET请求),此时你的后端能正常解析Authorization头,所以返回200。但正常前端请求中,因为携带了自定义的Authorization头,浏览器必须先做OPTIONS预检,只有预检请求返回200,才会自动发送后续的GET请求。

按照上面的步骤调整后,就能实现OPTIONS请求返回OK后自动执行GET请求的预期效果了。

内容的提问来源于stack exchange,提问作者Øystein Seel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:04:24