Beego中间件无法直接调用SetSession,因filter无Controller实例;需手动初始化globalSessions并调用SessionStart()操作session,且须defer SessionRelease()避免泄漏。

中间件里直接调用 SetSession 会失败
Beego 的 SetSession、GetSession 等方法绑定在 Controller 实例上,而中间件(filter)接收的是 *context.Context,没有 this 对象。强行在 filter 里调用会导致编译错误或 panic。
常见错误现象:在 InsertFilter 回调中写 this.SetSession("x", "y"),报错 undefined: this;或者误以为能通过 ctx.Input.CruContext 拿到 controller 实例——实际上它为空或未初始化。
- 中间件不是 controller 生命周期的一部分,不能访问 controller 方法
- Session 读写必须基于已启动的 session 实例,而该实例在 controller 的
Prepare()阶段才由框架自动调用StartSession()初始化 - 若真需在中间件操作 session,唯一可靠方式是手动调用 session manager
用 globalSessions.SessionStart() 手动启 session
Beego v2 默认不暴露全局 session manager,需自行初始化并复用。推荐在 main.go 初始化一次,存为包级变量:
由 ReMe 驱动的记忆管理系统,支持跨会话记忆持久化、自动应用用户偏好以及智能上下文压缩...
var globalSessions *session.Manager
func init() {
var err error
globalSessions, err = session.NewManager("redis", `{
"cookieName":"beegosessionID",
"enableSetCookie":true,
"gclifetime":3600,
"maxLifetime":3600,
"cookieLifeTime":86400,
"providerConfig":"127.0.0.1:6379,0,"
}`)
if err != nil {
panic(err)
}
go globalSessions.GC()
}
然后在 filter 中使用:
- 调用
sess, _ := globalSessions.SessionStart(w, r)获取 session 实例(w是http.ResponseWriter,r是*http.Request) -
sess.Set("key", value)写入,sess.Get("key")读取 - 务必
defer sess.SessionRelease(),否则内存泄漏或 redis 连接堆积 - 注意:此方式绕过 Beego 的 cookie path / domain / secure 等配置,需手动确保与 controller 行为一致
为什么不在中间件里做登录态校验?
多数场景下,你其实不需要在 filter 里读写 session 数据——比如权限拦截、token 刷新、埋点统计等,更适合放在 controller 的 Prepare() 方法里统一处理。
-
Prepare()在每个请求进入 action 前执行,天然持有this,可直接用this.GetSession() - Beego 的 session cookie 默认路径是
/,domain 为空,secure 取决于app.conf中secure = true配置,这些都由框架自动应用,filter 手动操作容易漏配 - 如果 filter 里提前读了 session,但后续 controller 又调用
this.GetSession(),可能拿到旧值(因 session 实例未刷新),造成逻辑不一致 - 跨域请求时,filter 中手动 set cookie 更难控制
SameSite和HttpOnly属性
app.conf 必须配对生效,否则 filter 里的 session 也无效
即使你手动初始化了 globalSessions,如果 Beego 主 session 开关没打开,浏览器根本不会发 beegosessionID Cookie,filter 拿到的 session ID 就是空或随机新生成的,所有读写都落空。
- 确认
conf/app.conf中有sessionon = true(注意不是session_on或其他拼写) - 必须同时指定
sessionprovider = "redis"(或"file"),否则 fallback 到"memory",多实例部署时数据不共享 -
sessiongcmaxlifetime和cookieLifeTime要匹配预期:前者控制服务端清理时间,后者控制浏览器 cookie 过期时间;差太多会导致“用户还登录着,后端已删 session” - 开发时容易忽略
copyrequestbody = true,导致 filter 中读不到 POST body,连带影响 token 解析和 session 关联逻辑
Prepare(),或上移到反向代理层(如 Nginx 做基础鉴权)。

















