Beego中间件中必须在BeforeRouter阶段显式调用ctx.Input.CruSession()获取session,且需确保conf/app.conf已启用sessionon=true、provider已配置并重启服务,否则Get操作恒返回nil。

中间件里不能直接调用 StartSession(),必须确保 Session 已全局启用
Beego 的 StartSession() 只在控制器中隐式调用(比如 this.GetSession() 会自动触发),但在中间件里不会自动初始化。如果中间件里直接写 ctx.Input.Session.Get("uid") 却没提前启动 session,结果永远是 nil,且无任何错误提示。
必须确认两点已生效:
-
conf/app.conf中设置了sessionon = true,且sessionprovider明确指定(如"redis") - 服务重启过——改配置不重启等于没改
- 中间件中需显式调用
ctx.Input.CruSession()(注意不是StartSession)来获取当前请求绑定的 session 实例
“记住我”逻辑必须放在中间件里做自动校验,而非仅靠控制器
用户勾选“记住我”后,登录成功时你写了加密的 remember_token cookie,但浏览器下次访问时,这个 token 不会自动变成 session 数据——得靠中间件主动读、验、续。
典型做法是在中间件中检查:ctx.GetCookie("beego_remember") 是否存在,若存在则:
- 解密 token,查数据库确认是否有效、未过期、未被注销
- 若通过,调用
ctx.Input.CruSession().Set("uid", userID)恢复会话 - 同时调用
ctx.SetCookie("beego_remember", newEncryptedToken, ...)刷新有效期(避免 token 过期后用户突然掉线) - 注意:不要在中间件里直接调用
this.SetSession()(this在中间件中不可用)
sessiongcmaxlifetime 和 cookieLifeTime 必须协同设置,否则“记住”失效不可控
中间件里恢复的 session,其服务端存活时间和浏览器 cookie 存活时间是两套机制,错配就会出现“cookie 还在但登录态没了”或“session 还在但 cookie 被浏览器删了”的情况。
例如你要支持 30 天“记住我”:
-
cookieLifeTime = 2592000(30 天秒数),控制浏览器 cookie 过期时间 -
sessiongcmaxlifetime = 2592000,否则 GC goroutine 一小时就清掉服务端数据,用户刷新页面就登出 - 若用 redis 作 provider,还需确认 redis key 的 TTL 与
sessiongcmaxlifetime一致(Beego 默认会设 redis EXPIRE,但自定义 provider 可能忽略)
中间件顺序决定会话可用性,BeforeRouter 是唯一安全位置
Beego 的中间件分 InsertFilter 类型:BeforeStatic、BeforeRouter、AfterExec 等。只有 BeforeRouter 阶段才能保证 ctx.Input.CruSession() 返回有效实例。
常见陷阱:
- 把会话校验逻辑放在
AfterExec—— 此时响应已生成,SetCookie或SetSession全部无效 - 误用
BeforeStatic—— 静态资源(如/static/js/app.js)请求也会进该中间件,白白消耗解密和 DB 查询 - 多个中间件都操作 session,未加锁可能导致并发写冲突(尤其是刷新 remember token 时)
sessionprovider = "redis" 时,remember token 校验的 DB 查询 + redis 写入必须原子化,否则高并发下可能生成重复 token 或漏刷新。这层逻辑不能只靠中间件堆砌,得结合应用层幂等设计和数据库唯一索引约束。


















