ReactJS无法从SpringBoot应用获取响应头问题排查
看起来你遇到的是典型的CORS响应头访问限制问题,结合你的代码来看,Postman能看到Authorization头但前端JS拿不到,核心原因是浏览器的同源策略默认会阻止JS访问非“CORS安全”的响应头,而Authorization不在默认允许的列表里,再加上你当前用RTK Query的方式也没拿到完整的响应对象,所以导致看不到headers。
下面分两步解决你的问题:
1. 后端SpringBoot配置:暴露响应头给前端
首先需要在SpringBoot端配置CORS,明确告诉浏览器允许前端访问Authorization这个响应头。你有两种方式实现:
方式一:在单个接口上添加注解
直接在你的登录接口方法上修改@CrossOrigin注解,加上exposedHeaders参数:
@PostMapping("/login") @CrossOrigin(exposedHeaders = "Authorization") // 关键:暴露Authorization头 public ResponseEntity<ApiResponse> loginUser(@RequestBody User user) { // 你的原有逻辑不变... String token = jwtUtil.generateToken(existingUser.getUsername(), existingUser.getRole()); UserDTO userDTO = userEntityToUserDTO.mapToDTO(existingUser); HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "Bearer " + token); return ResponseEntity.ok().headers(headers).body(new ApiResponse("Login successful", userDTO)); }
方式二:全局CORS配置(推荐,适合多接口场景)
如果你的应用有很多接口需要跨域,建议配置全局CORS规则:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class GlobalCorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 对所有接口生效 .allowedOrigins("http://localhost:3000") // 你的前端地址,生产环境替换成实际域名 .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .exposedHeaders("Authorization") // 必须明确暴露这个头 .allowCredentials(true) .maxAge(3600); } }
2. 前端RTK Query获取响应头的正确姿势
你当前用了.unwrap()方法,这个方法会直接返回响应的body数据,而不是完整的响应对象(包含headers、meta等信息)。要拿到headers,需要直接获取login mutation返回的完整结果:
修改你的handleLogin函数:
const handleLogin = async () => { if (!username || !password) { setError('Please fill in all fields'); return; } setError('') try { // 不要调用unwrap(),拿到完整的mutation结果 const loginResult = await login({ username, password }); // 从meta.response.headers中获取Authorization头 const token = loginResult.meta?.response?.headers.get('Authorization'); console.log('Authorization Header:', token); // 现在能在控制台看到了 if (token) { localStorage.setItem('token', token); } dispatch(setCredentials(loginResult.data)); navigate('/dashboard'); } catch (err) { console.log(err) setError(err.data?.message ? `Login failed: ${err.data.message}` : `Login failed: ${err.status}`); } };
为什么Postman能看到而Chrome控制台看不到?
Postman是独立的HTTP客户端,不受浏览器的**同源策略(CORS)**限制,所以能直接看到所有响应头;而浏览器为了安全,默认只允许JS访问Cache-Control、Content-Language、Content-Type等少数“CORS安全”的响应头,其他头必须由后端通过Access-Control-Expose-Headers响应头明确告知浏览器可以暴露给前端JS,这就是为什么你需要在SpringBoot里配置exposedHeaders("Authorization")的原因。
备注:内容来源于stack exchange,提问作者Indresh Mahor

