c.Cookie() 读不到 JSON 字符串是因为 net/http 要求 Cookie 值符合 RFC 6265,未转义的花括号、引号等非法字符会导致解析失败;正确做法是先 json.Marshal 再 base64 编码后存取。

直接用 c.Cookie() 读不到 JSON 字符串?
常见错误是:Cookie 值存的是 {"user_id":123,"role":"admin"},但调用 c.Cookie("token") 返回 http: named cookie not found 或空值。这不是 Gin 的 bug,而是 net/http 包对 Cookie 值的解析规则导致的——它要求 Cookie 值必须符合 RFC 6265,不能含未转义的花括号、冒号、引号等字符。浏览器实际发送时会自动 URL 编码,但如果你手动拼接 JSON 字符串塞进 SetCookie,服务端就无法识别。
c.Cookie() 返回的是原始未解码值
即使 Cookie 值是合法的(比如 user_id=123&role=admin),c.Cookie() 返回的也是未经 URL 解码的原始字符串。这意味着:
- 如果服务端用
url.QueryEscape编码后设置,客户端返回时仍是编码态,需手动url.QueryUnescape - JSON 字符串必须先做
url.PathEscape或url.QueryEscape,否则会被net/http拒绝解析 -
c.Cookie()不会帮你解析成 map 或 struct,它只返回 string
安全地存取 JSON 数据的推荐做法
别把裸 JSON 当 Cookie 值直存。正确路径是:
- 用
json.Marshal()序列化结构体 → 得到字节切片 - 用
base64.StdEncoding.EncodeToString()编码 → 得到安全字符串(无特殊字符) - 传给
c.SetCookie("auth", encoded, 3600, "/", "localhost", false, true) - 读取时:
raw, err := c.Cookie("auth")→decoded, _ := base64.StdEncoding.DecodeString(raw)→json.Unmarshal(decoded, &v) - 避免用
httpOnly=false存敏感 JSON,防止 XSS 泄露
为什么 maxAge=-1 不能总删掉 Cookie
设 maxAge=-1 确实会触发浏览器删除动作,但前提是 domain/path 与设置时完全一致。容易踩的坑:
- 设置时用了
domain="localhost",删除时却漏写 domain 参数 → 浏览器找不到匹配项,不删 - 设置时 path 是
"/api",删除时用"/"→ 不匹配,无效 - 开发环境用
localhost,生产环境用域名,跨环境删除必须同步 domain 配置 - HTTPS 环境下 secure=true,HTTP 请求里删不掉,因为浏览器根本不会发这个 Cookie 上来
真正要删干净,得复用当初设置时的全部参数,尤其是 domain 和 path —— 这点很容易被忽略,一删就残留。


















