为何浏览器与Node.js中Axios的Cookie响应头存在差异?
问题现象
我在用Create React App搭建的React项目中,通过axios调用API获取Cookie时出现两种不同表现:
- 浏览器端:控制台打印axios响应头时找不到
set-cookie属性,但Application面板的Cookies中能看到Cookie已被正常存储; - Node.js端:用axios调用同一API,响应头里明确包含
set-cookie属性。
想明确浏览器端set-cookie消失的原因,以及两种环境的差异所在。
运行环境
- OS: Ubuntu 20.04.5 LTS
- 浏览器: Google Chrome Version 106.0.5249.91 (Official Build) (64-bit)
- Node.js 16.13.0
- react-scripts 5.0.1
- axios 0.27.2
相关代码
浏览器端代码(App.tsx)
import "./App.css"; import axios, { AxiosRequestConfig, AxiosResponse } from "axios"; function App() { const handleClick = () => { const options: AxiosRequestConfig = { url: "/cookie", method: "GET", withCredentials: true, }; axios(options).then((resp: AxiosResponse) => { console.log(resp.headers); }); }; return ( <div className="App"> <button onClick={handleClick}>Get Cookie</button> </div> ); } export default App;
代理配置补充(package.json)
为解决CORS问题,在package.json中设置了代理:
// package.json { ... "scripts": { "start": "react-scripts start", ... }, ... "proxy": "http://localhost:8080" }
Node.js端代码(index.js)
const axios = require("axios"); const getCookie = () => { const options = { url: "http://localhost:8080/cookie", method: "GET", withCredentials: true, }; axios(options) .then((resp) => { console.log(resp.headers); }) .catch((e) => { console.log(e); }); }; getCookie();
运行方式:终端执行
node index.js
API服务端代码(server.go)
package main import ( "fmt" "io/ioutil" "log" "net/http" ) func cookieHandler(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { http.Error(w, "Method is not supported", http.StatusNotFound) return } w.Header().Set("Access-Control-Allow-Headers", "Content-Type, x-requested-with") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") w.Header().Set("Access-Control-Allow-Credentials", "true") w.Header().Set("Access-Control-Expose-Headers", "Set-Cookie") http.SetCookie(w, &http.Cookie{ Name: "sampleName", Value: "sampleValue", HttpOnly: false, Path: "/", }) fmt.Fprintf(w, "Hello") } func main() { http.HandleFunc("/cookie", cookieHandler) fmt.Printf("starting server at port 8080\n") if err := http.ListenAndServe(":8080", nil); err != nil { log.Fatal(err) } }
原因解析
1. 浏览器的安全机制限制
浏览器为了防范XSS等安全风险,会自动拦截Set-Cookie响应头,将Cookie直接存储到对应域名的Cookie仓库中,不会把Set-Cookie暴露给前端JavaScript代码。哪怕你在CORS配置中设置了Access-Control-Expose-Headers: Set-Cookie,也无法绕过这个原生限制——这是浏览器同源策略和Cookie安全体系的核心设计,目的是避免恶意脚本窃取敏感Cookie信息。
2. Node.js环境的无限制特性
Node.js作为服务端运行环境,不存在浏览器的前端安全限制。axios在Node.js中作为纯HTTP客户端,会直接获取完整的响应头内容,包括Set-Cookie,因为Node.js不需要处理前端页面的安全风险。
3. 代理的影响说明
你在React项目中设置的开发代理,只是负责转发请求和响应,它会把后端的Set-Cookie头转发给浏览器,但浏览器依然会按照安全规则拦截该头,不让JS访问,只执行存储操作。所以代理不是导致Set-Cookie消失的原因,核心还是浏览器的安全机制。
浏览器端获取Cookie的正确方式
既然Cookie已经被浏览器存储,你可以通过document.cookie读取非HttpOnly的Cookie(你的Cookie设置了HttpOnly: false,符合读取条件)。示例代码:
axios(options).then((resp: AxiosResponse) => { console.log(document.cookie); // 输出:sampleName=sampleValue });
内容的提问来源于stack exchange,提问作者Yasu

