Cookie原生不支持二进制,必须用Base64编码为ASCII字符串存储;UTF-8仅适用于Unicode文本,不能用于任意二进制数据;需注意大小限制、HttpOnly设置及先加密再编码等安全实践。

Cookie 原生不支持二进制,必须编码后存 ASCII 字符
浏览器只接受 Set-Cookie 响应头中符合 RFC6265 的 ASCII 字符序列,原始二进制数据(如图片字节、加密密钥)直接写入会触发解析错误或被截断。你看到的“存二进制”本质是编码后的字符串 —— 这不是框架限制,而是 HTTP 协议层硬性要求。
Base64 是最稳妥的二进制编码方案
Base64 将任意字节流转为 A–Z、a–z、0–9、+、/ 和 = 组成的纯 ASCII 字符串,兼容所有浏览器和 Echo 的 c.SetCookie() 接口。它比 URL 编码更紧凑,解码无歧义,且 Go 标准库 encoding/base64 开箱即用。
- 编码示例:
import "encoding/base64" data := []byte{0xff, 0x00, 0xaa} encoded := base64.StdEncoding.EncodeToString(data) // 得到 "/wCq" - 写入 Cookie:
cookie := &http.Cookie{ Name: "img_data", Value: encoded, Path: "/", MaxAge: 3600, } c.SetCookie(cookie) - 读取并解码:
cookie, err := c.Cookie("img_data") if err != nil { // 处理 http.ErrNoCookie 或其他错误 } decoded, err := base64.StdEncoding.DecodeString(cookie.Value) if err != nil { // 解码失败:可能被篡改或损坏 }
UTF-8 编码只适用于 Unicode 文本,不解决二进制问题
如果你存的是中文、emoji 等 Unicode 字符串,utf8 编码是默认且正确的选择 —— Go 字符串本身已是 UTF-8 编码的字节序列,直接赋值给 http.Cookie.Value 即可。但注意:这不等于能存二进制。若误将非 UTF-8 字节(如 PNG 文件头)当字符串传入,len() 和遍历行为会出错,且部分浏览器可能静默丢弃。
- 正确(文本):
c.SetCookie(&http.Cookie{Name: "user_name", Value: "张三"}) - 错误(伪二进制):
c.SetCookie(&http.Cookie{Name: "raw", Value: string([]byte{0xff, 0x00})})—— 这会产生无效 UTF-8,后续json.Marshal或模板渲染可能 panic
别踩这些坑:大小、安全与类型混淆
即使编码后,Cookie 仍受协议约束。实际部署时最容易翻车的是这几个点:
-
MaxAge和Expires必须显式设置,否则默认为会话 Cookie(浏览器关闭即丢),不是编码问题,但常被忽略导致“存了却读不到” - 单个 Cookie 值不能超过 4096 字节 —— Base64 编码后体积膨胀约 33%,原数据建议控制在 ~3KB 以内
-
http.Cookie.HttpOnly = true必须设,否则前端 JS 可读取 Base64 数据并尝试解码,XSS 场景下等于白忙活 - 不要把 Base64 字符串再套一层
url.QueryEscape——+和/在 Cookie 值里合法,双重编码反而导致解码失败
Base64 编码本身不提供保密性,敏感二进制数据(如 token 加密载荷)必须先加密再 Base64,且密钥绝不能硬编码在客户端。Cookie 容量和安全性边界比想象中窄,真正需要存大量或高敏二进制数据时,该走服务端临时存储 + ID 引用。











