优先选max_age(单位秒),因其符合rfc 6265标准、免时区转换、浏览器兼容性好;若同时设置,max_age会覆盖expires。

set_cookie() 的 max_age 和 expires 参数怎么选
在 Fiber 中设置 Cookie 生命周期,核心就靠 set_cookie() 方法的两个参数:max_age 和 expires。它们不互斥,但有明确优先级:如果同时传入,max_age 会覆盖 expires。
实际开发中推荐优先用 max_age(单位秒),原因很实在:
-
max_age是 RFC 6265 标准字段,所有现代浏览器都支持,包括移动端 WebView -
expires要求传入 UTC 时间戳,本地开发时容易因时区搞错——比如用time.Now().Add(24 * time.Hour)直接赋值,结果浏览器按 GMT 解析,相当于少 8 小时 - Fiber 内部对
max_age的处理更直接,不依赖时间格式解析,出错概率低
如何用 set_cookie() 设置 7 天有效期的 Cookie
这是最常见需求,但写错会导致 Cookie 立刻失效或变成会话级(关浏览器就丢)。
正确做法是明确传入整数秒值:
ctx.SetCookie(&fiber.Cookie{
Name: "session_id",
Value: "abc123",
MaxAge: 7 * 24 * 3600, // ✅ 604800 秒,不是字符串也不是 time.Time
Path: "/",
Domain: "example.com",
HTTPOnly: true,
Secure: true,
SameSite: "Lax",
})
注意几个易错点:
-
MaxAge字段必须是int类型,传int64或time.Duration会静默失败(Fiber 不做类型转换) - 如果
Secure: true但服务跑在 HTTP 上,浏览器会直接拒绝存储该 Cookie,且不报错 -
Domain值不能带协议(如https://example.com),也不能以点开头(如.example.com),否则部分浏览器(尤其是 Safari)会忽略
动态计算过期时间时为什么不能直接用 time.Now().Add()
因为 expires 字段要求的是绝对时间点(UTC),而 time.Now().Add() 返回的是本地时区时间。Fiber 不会自动转时区,它原样塞进 Expires 响应头,浏览器按 RFC 解析时就会偏差。
如果你非要用 expires(比如兼容极老客户端),必须显式转成 UTC:
expiry := time.Now().Add(7 * 24 * time.Hour).UTC()
ctx.SetCookie(&fiber.Cookie{
Name: "token",
Value: "xyz",
Expires: expiry,
})
但更稳妥的做法是绕开这个坑:直接算秒数,走 MaxAge。连时区转换都省了。
CSRF Cookie 的生命周期要单独控制吗
要。Fiber 的 CSRF 中间件(csrf.New())默认生成的 __Host-csrf_ Cookie 是会话级的(即关浏览器就失效),即使你全局设置了长生命周期的 session Cookie,CSRF Token 也不会继承。
若需延长 CSRF Cookie 有效期,必须显式配置:
app.Use(csrf.New(csrf.Config{
CookieMaxAge: 3600 * 24 * 7, // ✅ 显式设为 7 天
CookieName: "__Host-csrf_",
CookieSecure: true,
CookieHTTPOnly: true,
CookieSameSite: "Lax",
}))
这里的关键是 CookieMaxAge 字段——它和路由响应里的 MaxAge 是两套逻辑,不互通。漏配这个,前端发 POST 请求时大概率收到 403。
真正麻烦的不是设多长,而是不同 Cookie 类型(普通业务 Cookie、CSRF Token、Session ID)各自有一套生命周期控制入口,且命名不统一。一不留神就只改了其中一种,导致登录态还在但表单提交总失败。











