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

React+Spring Boot跨域时无法获取响应Authorization头,求解决方法

问题:启用CORS后无法读取响应头里的Authorization(JWT Token)

登录接口返回的JWT Token放在响应头的Authorization字段中,前端之前能正常读取,但后端启用Spring Security的cors()配置后,前端再也拿不到这个字段了。后端返回的响应头里确实存在Authorization字段,但前端就是访问不到。

前端登录函数代码

const username = useRef();
const password = useRef();
const navigate = useNavigate();

function loginHandler() {
    axios.post("/auth/login", {
        username: username.current.value,
        password: password.current.value
    })
    .then((response) => {
        console.log(response.headers)
        window.localStorage.setItem("token", response.headers.get("Authorization"))
        navigate("/shoes/mens")
    });
}

后端Spring Security配置代码

@Override
protected void configure(HttpSecurity http) throws Exception {

    http = http.csrf().disable().cors().and();

    http = http.sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and();

    http = http.exceptionHandling()
            .authenticationEntryPoint((request, response, ex) -> {
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage());
            }).and();

    http.authorizeRequests()
            .antMatchers("/auth/**").permitAll()
            .antMatchers("/storage/**").hasAuthority("ROLE_EMPLOYEE")
            .anyRequest().authenticated();

    http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);

}

解决方法

问题根源是CORS的默认限制:浏览器只允许前端访问预设的CORS安全响应头(比如Content-Type、Cache-Control这些),像Authorization这种自定义头不在默认列表里,哪怕后端返回了,前端也读不到。

必须在Spring Boot的CORS配置里显式声明要暴露Authorization头,下面给两种实现方式:

方式1:全局CORS配置(@Bean)

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        // 允许的前端域名,根据实际情况改,不要随便用*(带凭证时*无效)
        config.setAllowedOriginPatterns(Arrays.asList("http://localhost:3000"));
        // 允许的请求方法
        config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        // 允许的请求头
        config.setAllowedHeaders(Arrays.asList("*"));
        // 核心:告诉浏览器可以暴露Authorization头给前端
        config.setExposedHeaders(Arrays.asList("Authorization"));
        // 允许携带Cookie等凭证(如果业务需要的话)
        config.setAllowCredentials(true);
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

方式2:在Security配置中集成CORS配置

直接修改你现有的Security配置类,把默认的.cors()换成自定义的配置源:

@Override
protected void configure(HttpSecurity http) throws Exception {
    // 替换默认cors配置,使用自定义的配置源
    http = http.csrf().disable().cors(cors -> cors.configurationSource(corsConfigurationSource())).and();

    // 下面的原有配置保持不变
    http = http.sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and();

    http = http.exceptionHandling()
            .authenticationEntryPoint((request, response, ex) -> {
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage());
            }).and();

    http.authorizeRequests()
            .antMatchers("/auth/**").permitAll()
            .antMatchers("/storage/**").hasAuthority("ROLE_EMPLOYEE")
            .anyRequest().authenticated();

    http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}

// 自定义CORS配置源
private CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowedOriginPatterns(Arrays.asList("http://localhost:3000"));
    config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
    config.setAllowedHeaders(Arrays.asList("*"));
    config.setExposedHeaders(Arrays.asList("Authorization"));
    config.setAllowCredentials(true);
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);
    return source;
}

注意事项

  • setExposedHeaders是关键操作,必须加上才能让前端读到Authorization头。
  • 允许的源要根据实际前端地址设置,本地开发一般是http://localhost:端口号,生产环境换成实际域名。
  • 配置完重启后端,前端再登录就能在response.headers里看到Authorization字段了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:35:19