不能直接用 http.Cookie 存用户身份,因为其明文传输且无完整性校验,攻击者可篡改 user_id 绕过登录;需用 gorilla/securecookie 签名(防篡改)或加密(防读取),并手动校验 exp、服务端二次鉴权。

Go 标准库的 http.SetCookie 和 http.Request.Cookies() 本身不提供加密或签名能力,直接存敏感信息(如用户 ID、权限)到 Cookie 是危险的。必须自行实现签名或加密,否则容易被篡改或窃取。
为什么不能直接用 http.Cookie 存用户身份?
标准 http.Cookie 是明文传输(即使走 HTTPS,服务端也无法验证是否被客户端修改过)。攻击者可伪造 user_id=123 并手动设置 Cookie 绕过登录校验。
- 没有完整性保护 → 攻击者可任意修改值
- 没有机密性保护 → 敏感字段(如角色、过期时间)暴露在客户端
-
Secure和HttpOnly只是传输/访问限制,不解决内容可信问题
用 gorilla/securecookie 实现签名+可选加密
这是最常用、经过实战检验的方案。它默认只做 HMAC 签名(防篡改),开启 Encode/Decode 时可额外 AES 加密(防读取)。
import (
"github.com/gorilla/securecookie"
)
var s = securecookie.New(
securecookie.GenerateRandomKey(32), // auth key
securecookie.GenerateRandomKey(32), // encrypt key (only if using encryption)
)
// 写入带签名的 Cookie
func setAuthCookie(w http.ResponseWriter, userID string) {
encoded, err := s.Encode("auth", map[string]interface{}{"id": userID, "exp": time.Now().Add(24 * time.Hour).Unix()})
if err != nil {
http.Error(w, "encoding failed", http.StatusInternalServerError)
return
}
http.SetCookie(w, &http.Cookie{
Name: "auth",
Value: encoded,
Path: "/",
HttpOnly: true,
Secure: true, // 仅 HTTPS
SameSite: http.SameSiteStrictMode,
MaxAge: 86400,
})
}
- 必须把两个密钥(auth + encrypt)安全保存,不要硬编码在代码里
- 如果只签名不加密,第二个密钥可传
nil;但只要含敏感字段(如角色),就应启用加密 -
SameSite建议设为Strict或Lax,缓解 CSRF
手动验证 Cookie 时必须检查 exp 字段并拒绝过期数据
securecookie 不自动校验过期时间,它只保证数据未被篡改。你必须在解码后手动检查 exp 是否小于当前时间。
立即学习“go语言免费学习笔记(深入)”;
func getAuthFromRequest(r *http.Request) (string, error) {
cookie, err := r.Cookie("auth")
if err != nil {
return "", errors.New("no auth cookie")
}
var value map[string]interface{}
if err := s.Decode("auth", cookie.Value, &value); err != nil {
return "", errors.New("invalid or tampered cookie")
}
if exp, ok := value["exp"].(float64); !ok || int64(exp) < time.Now().Unix() {
return "", errors.New("cookie expired")
}
if id, ok := value["id"].(string); ok {
return id, nil
}
return "", errors.New("missing user id")}
- 类型断言要小心:
securecookie解码 JSON 后数字默认是float64 - 不要信任任何来自 Cookie 的字段(包括
role、email),只用于查库或生成 session,关键权限必须服务端二次确认 - 避免在 Cookie 中存密码哈希、token 原文等高危信息
真正难的不是加解密逻辑,而是密钥生命周期管理、过期策略与业务上下文的耦合——比如用户登出时如何让旧 Cookie 失效?这需要配合服务端黑名单或短有效期+刷新机制,单纯靠 Cookie 自身无法解决。










