必须用c.SetCookie()而非http.SetCookie(),因Echo框架封装了Header写入逻辑;需传*http.Cookie指针,Name/Value必填,Path建议"/",MaxAge或Expires二选一,生产环境须设Secure:true、HttpOnly:true、SameSite:Lax/Strict。

必须用 c.SetCookie(),不能手动调用 http.SetCookie() —— 否则 Header 冲突、Cookie 被静默丢弃。
怎么正确初始化并写入 Cookie
Echo 的 SetCookie() 接收一个已构造好的 *http.Cookie 指针,不是键值对。常见错误是传字符串或 map,这会编译失败或 panic。
- 用
new(http.Cookie)或字面量初始化,再赋值关键字段 -
Name和Value是必填项;Path建议设为"/",否则可能读不到 -
MaxAge和Expires二选一即可:MaxAge = -1表示删除,MaxAge = 0表示会话级(关浏览器失效) - 生产环境务必设
Secure: true(仅 HTTPS)、HttpOnly: true(防 XSS),SameSite: http.SameSiteLaxMode或http.SameSiteStrictMode
cookie := &http.Cookie{
Name: "auth_token",
Value: "abc123",
Path: "/",
MaxAge: 3600,
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
}
c.SetCookie(cookie)
读取 Cookie 时为什么总是报 http.ErrNoCookie
这是最常踩的坑:c.Cookie("name") 返回 *http.Cookie 和 error,如果客户端没发该 Cookie,err 就是 http.ErrNoCookie,不是 nil。直接忽略 err 会导致后续 panic。
- 永远先检查 error,不要假设 Cookie 一定存在
- 不要对
cookie.Value做空值判断就完事 —— 如果c.Cookie()失败,cookie是 nil,取.Value会 panic - 批量读取用
c.Cookies(),适合调试或灰度场景,但注意它不校验HttpOnly等属性,只返回原始请求头里的全部 Cookie
cookie, err := c.Cookie("auth_token")
if err != nil {
if errors.Is(err, http.ErrNoCookie) {
return c.String(http.StatusUnauthorized, "missing auth_token")
}
return err
}
token := cookie.Value // 此时 cookie 非 nil,可安全取值
为什么设置了 Cookie 却在下个请求里读不到
除了前端没带、路径/域名不匹配外,最隐蔽的原因是:服务端没配 Domain 或配错了,导致浏览器认为不属于当前域而拒绝发送。
-
Domain字段必须显式设置才能跨子域共享;若留空,浏览器默认设为「完整主机名」(如api.example.com),www.example.com就读不到 - 想让
example.com和所有子域共用,Domain必须设为".example.com"(开头带点) -
Secure设为true但走 HTTP 请求时,浏览器直接忽略该 Cookie,不会发给服务端 - 前端 JS 用
fetch发请求时,记得加credentials: 'include',否则 Cookie 不自动携带
Session 依赖 Cookie,但和 Cookie 不是一回事
很多人以为“用了 c.SetCookie() 就等于有了 Session”,其实完全不是。Echo 本身不带 Session 支持,session.Middleware() 是独立中间件,且必须提前注册。
- 没注册中间件就调
session.Get(c),返回的sess是 nil,sess.Values["key"]直接 panic -
sessionKey必须 ≥ 32 字节,用短字符串(如"123")会导致crypto/aes初始化失败 - Cookie 名(如
"user_session")和后端存储 key 必须严格一致,大小写敏感,拼错一个字母就读不到 session 数据 -
sess.Values是map[string]interface{},取值后必须做类型断言:id, ok := sess.Values["id"].(int),否则运行时报错
真正容易被忽略的是:Cookie 过期时间和 Session 存储过期时间要协同。比如 Cookie MaxAge=3600,但 Redis 中 session TTL 设了 86400,用户 Cookie 失效后仍能通过旧 ID 访问 session 数据 —— 这属于逻辑漏洞。


















