gin中cookie值含json时需先url.queryescape()编码再setcookie,否则因net/http校验失败导致c.cookie()报“named cookie not present”;读取时c.cookie()已自动解码,可直接json.unmarshal。

Cookie值含JSON结构时无法直接用c.Cookie()获取
当你把 JSON 字符串(比如 {"user_id":123,"role":"admin"})作为 Cookie 值写入,再调用 c.Cookie("auth") 会返回错误 http: named cookie not present —— 并不是没设上,而是 net/http 底层对 Cookie 值做了严格校验:它要求值必须是「token」或带引号的字符串,且不能包含未转义的花括号、冒号、空格等。原始 JSON 直接塞进去会被静默丢弃或解析失败。
- 不要手动拼接 JSON 字符串后直接传给
c.SetCookie() - 必须先用
url.QueryEscape()编码,否则服务端设不成功,客户端也发不回来 -
c.Cookie()内部已自动调用url.QueryUnescape(),所以你只需确保设的时候编码了,取的时候就能拿到原始 JSON 字符串
正确设置和读取带JSON的Cookie
核心是绕过 net/http 对 Cookie 值的非法字符拦截。Gin 的 c.SetCookie() 底层调用了 http.SetCookie(),而后者会对 Value 字段做预处理;但如果你跳过 Gin 封装、直接操作 http.Cookie 并手动 escape,就能安全存 JSON。
- 设 Cookie 时:用
url.QueryEscape()包一层 JSON 字符串,再传给c.SetCookie() - 读 Cookie 时:
c.Cookie()返回的就是已 unescape 后的原始 JSON 字符串,可直接json.Unmarshal() - 示例代码中注意:不要在
SetCookie的value参数里传 raw JSON,要传url.QueryEscape(jsonStr)
// 设置
jsonBytes, _ := json.Marshal(map[string]interface{}{"user_id": 123, "role": "admin"})
escaped := url.QueryEscape(string(jsonBytes))
c.SetCookie("auth", escaped, 3600, "/", "localhost", false, true)
// 获取并解析
cookieVal, err := c.Cookie("auth")
if err != nil {
c.AbortWithStatus(400)
return
}
var data map[string]interface{}
json.Unmarshal([]byte(cookieVal), &data) // cookieVal 此时已是原始 JSON 字符串
跨子域名共享多层结构Cookie需显式指定Domain
若前端请求来自 app.example.com,但你想让 api.example.com 也能读到同一个 auth Cookie,仅靠路径 / 不够——必须把 Domain 设为 .example.com(注意开头的点),且不能设成 localhost 或 IP 地址(浏览器会拒绝)。
- 本地开发时用
Domain: "localhost"是 OK 的,但正式环境必须用带点的二级域通配,如".example.com" - Chrome 和新版 Firefox 对
Domain值校验变严:设成example.com(无点)可能被忽略,必须.example.com - 如果前后端分离且部署在不同子域,还要配合 CORS 头:
Access-Control-Allow-Credentials: true和精确的Access-Control-Allow-Origin(不能是*)
httpOnly 和 Secure 开关的实际影响
这两个布尔参数不是“锦上添花”,而是安全边界。设错会导致 Cookie 在特定场景下完全不可见:
-
httpOnly: true→ 前端 JS 拿不到document.cookie,但 Gin 的c.Cookie()仍能读;这是防 XSS 的关键一环,生产环境建议始终开启 -
Secure: true→ Cookie 只随 HTTPS 请求发送;若你在 HTTP 环境(如本地http://localhost:8080)设了Secure: true,浏览器会直接丢弃该 Cookie,后续任何请求都带不上 - 调试时容易忽略:本地启 HTTP 服务却误设
Secure: true,导致反复查不到 Cookie,其实只是被浏览器过滤了
复杂点在于,多层结构本身不增加解析难度,难的是让 Cookie “稳稳抵达”并被正确解码。真正卡住人的往往不是 JSON 解析逻辑,而是 URL 编码遗漏、Domain 写错、Secure 误开这些底层细节。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











