Metabase 会话过期机制完全指南:MAX_SESSION_AGE、MB_SESSION_TIMEOUT 与 MB_SESSION_COOKIES 配置详解
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
Metabase 的会话(Session)是登录态得以跨标签页、跨页面保持的核心机制,而如何让会话按预期过期、何时强制登出用户,直接关系到系统的安全性与用户体验。本文以 Metabase 官方文档 changing-session-expiration.md 为主体骨架,结合当前仓库的会话中间件、Cookie 处理与定时清理任务的源码实现,系统讲解会话过期相关的三组配置:绝对会话上限MAX_SESSION_AGE、不活跃超时MB_SESSION_TIMEOUT与强制会话 CookieMB_SESSION_COOKIES。读完本文,你将掌握每种过期方式的适用场景、精确的配置语法与参数取值范围,并理解它们在底层是如何协同生效的。
会话的生命周期:Metabase 如何维持登录态
当用户通过邮箱密码或 SSO 登录时,Metabase 会创建一个会话,使其在切换标签页、刷新页面的过程中保持登录状态。从 src/metabase/server/middleware/session.clj 的命名空间文档可以看到认证的两条主要路径:
- 会话(Session)认证:登录成功后自动写入名为
metabase.SESSION的 Cookie,该 Cookie 为 HttpOnly 属性,前端代码无法读取;全应用嵌入(full-app embedding)场景下则为metabase.EMBEDDED_SESSION。此外请求头X-Metabase-Session也可用于认证,此时两个 Cookie 会被忽略。 - API Key 认证:通过
X-Api-Key请求头匹配数据库中的 API Key,适用于服务端自动化调用场景,与会话过期机制无关。
会话可以通过以下三种方式结束,这也是本文后续三个章节的主题:
- 关闭浏览器(受 Cookie 类型与
MB_SESSION_COOKIES影响); - 达到绝对会话年龄上限(
MAX_SESSION_AGE,从登录时刻开始计时); - 持续不活跃达到超时窗口(
MB_SESSION_TIMEOUT,从最后一次活动时刻开始计时)。
需要特别说明的是:手动清除浏览器 Cookie 或缓存会立即结束会话,这一行为不受上述任何设置的约束。
设定绝对会话上限:MAX_SESSION_AGE
语义与默认值
MAX_SESSION_AGE控制一个会话从登录时刻起最多可以存活多少分钟。例如用户打开了数百个标签页且数月未重启浏览器,只要达到MAX_SESSION_AGE就会被登出——即便登录时勾选了Remember me(记住我)复选框也无法豁免,因为该上限是强制性的。
- 类型:整数
- 默认值:
20160(即 14 天),见 src/metabase/cmd/resources/other-env-vars.md - 设置方式:仅支持环境变量。上述文档明确写道:
MAX_SESSION_AGE只能通过环境变量设置,无法通过配置文件(config文件)修改。
配置示例
以分钟为单位设置自定义值,例如让会话在 24 小时后过期:
# 会话在 24 小时后过期 MAX_SESSION_AGE=1440 java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar该设置对所有人一视同仁,不区分浏览器行为或活动模式。当安全策略要求用户按可预测的周期重新登录时(例如每 24 小时或每周强制重新认证一次),应使用此配置。
底层生效机制
MAX_SESSION_AGE在源码中的生效路径分为三层:
- Cookie 有效期:在 src/metabase/request/cookies.clj 中,会话 Cookie 的
Max-Age默认值由(* 60 (config/config-int :max-session-age))计算(分钟换算为秒)。也就是说,即使浏览器不关闭,Cookie 本身也会在到达上限后过期。 - 服务端校验:在 src/metabase/server/middleware/session.clj 中,每次请求解析会话时会传入
(config/config-int :max-session-age),由应用数据库查询判断会话是否已过期(详见 src/metabase/server/db.clj 中的会话用户信息查询)。 - 定时清理:Metabase 内置的 SessionCleanup 任务每天凌晨 2 点(cron 表达式
0 0 2 * * ? *)运行一次,删除超出MAX_SESSION_AGE、超过自身expires_at、或超过不活跃阈值的会话记录,见 src/metabase/session/task/session_cleanup.clj。其底层 SQL 位于 src/metabase/session/db.clj。
注意:
MAX_SESSION_AGE不是空闲/不活跃超时。若将其设为 15 分钟,用户每 15 分钟就必须重新登录(或重新认证)一次,无论期间是否活跃。控制"不活跃多久后登出"应使用MB_SESSION_TIMEOUT。
按不活跃时长登出:MB_SESSION_TIMEOUT
功能定位与授权前提
MB_SESSION_TIMEOUT控制会话在不活跃多长时间后结束。例如用户早上打开 Metabase,用了一小时,之后一整天都在其他工具中工作,一旦不活跃时间超过设定窗口就会被登出。
该功能属于Metabase 付费版(EE)特性:在 src/metabase/premium_features/settings.clj 中定义了enable-session-timeout-config?,并映射到特性令牌:session-timeout-config。对应地,测试 test/metabase/server/middleware/session_test.clj 验证了:未启用该付费特性时,即便设置了session-timeout,会话也不会因此过期。
两种配置方式
方式一:管理员界面。进入Admin(管理后台)>Authentication(认证)>Overview(概览)页面配置。需要说明的是,界面中只能以**分钟(minutes)或小时(hours)**为单位指定超时时间。
方式二:环境变量。使用 JSON 格式的字符串,单位支持seconds(秒)、minutes(分钟)、hours(小时):
# 不活跃 2 小时后登出 MB_SESSION_TIMEOUT='{"amount":120,"unit":"minutes"}' java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar环境变量相较界面配置多支持"unit":"seconds",这在与测试、自动化脚本对齐时更为灵活。
参数校验规则
从 src/metabase/request/settings.clj 的session-timeout设置定义可以确认以下规则:
- 值必须是 JSON 对象,形如
{"amount":120,"unit":"minutes"},unit只能是seconds、minutes、hours三者之一; amount必须为正数(amount-must-be-positive),且不能达到 100 年(amount-must-be-less-than-100-years);- 校验失败时,通过 API 或界面设置会返回 HTTP 400,并附带明确的错误信息;环境变量方式下则记录警告并回退为
nil(即不启用超时)。
此外,src/metabase/request/cookies.clj 中的session-timeout->seconds函数将所有单位统一换算为秒,并强制最小值 60 秒——这是为了防止管理员误设过短的时间导致用户把自己锁在门外。对应测试见 test/metabase/request/cookies_test.clj 与 test/metabase/request/settings_test.clj。
什么算"活跃"?
这一点直接影响实际效果,官方文档给出了两条关键行为:
- 开启自动刷新(auto-refresh)的仪表盘即使在后台标签页中,也会持续产生请求,因此计入活跃,能不断刷新不活跃计时器;
- 定时告警(scheduled alerts)与仪表盘订阅(dashboard subscriptions)是服务端任务,不会重置用户的不活跃计时器——它们本质上与用户是否在线无关。
从实现上看,src/metabase/server/middleware/session.clj 的maybe-update-session-activity!会更新会话的last_active_at字段,并做了节流(throttle)处理以避免每个请求都触发数据库写入。清理任务删除空闲会话时,使用的是COALESCE(last_active_at, created_at)——即优先以最后活跃时间、缺失时回退到创建时间来判断空闲时长(见 src/metabase/session/db.clj)。
提示:仅当启用了会话超时(即
MB_SESSION_TIMEOUT已配置)时,活跃度跟踪才会被激活。
MAX_SESSION_AGE与MB_SESSION_TIMEOUT如何协同
当两者同时配置时,会话在"先到达"的那个限制处结束——无论用户是否活跃,绝对年龄上限都会在MAX_SESSION_AGE分钟后来临;而如果用户在达到年龄上限之前就长时间不活跃,则会先被MB_SESSION_TIMEOUT登出。
| 维度 | MAX_SESSION_AGE | MB_SESSION_TIMEOUT |
|---|---|---|
| 计时起点 | 登录时刻 | 最后一次活跃时刻 |
| 默认值 | 20160 分钟(14 天) | 未配置(无限期) |
| 配置位置 | 仅环境变量 | 管理界面或环境变量 |
| 授权要求 | 所有版本 | 付费版(EE)特性 |
| 适用场景 | 定期强制重新认证 | 共享工作站、遗忘的打开标签页 |
正是由于这种互补性,MB_SESSION_TIMEOUT特别适合共享工作站、容易遗留的打开标签页,以及任何"长时间闲置会话构成安全隐患"的场景:即使不活跃超时窗口内用户一直开着浏览器,MAX_SESSION_AGE也始终是兜底的绝对上限。
强制所有人使用会话 Cookie:MB_SESSION_COOKIES
行为差异
默认情况下,登录页的Remember me复选框是勾选状态,因此会话使用持久 Cookie,可以跨浏览器关闭与重启存活;取消勾选后,关闭浏览器即结束会话。
MB_SESSION_COOKIES=true会改变这一默认行为:
# 强制使用会话 Cookie:关闭浏览器即登出,且移除登录页的 Remember me 复选框 MB_SESSION_COOKIES=true java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar设置后:
- 登录页的Remember me复选框会被移除;
- 所有用户统一采用会话 Cookie(session cookie),浏览器关闭即登出;
- 但
MAX_SESSION_AGE与MB_SESSION_TIMEOUT仍然生效——从不关闭浏览器的用户同样可能被年龄上限或不活跃窗口登出。
底层实现
在 src/metabase/session/settings.clj 中,session-cookies设置默认值为false,其文档注释明确指出:"用户登录会话总会按MAX_SESSION_AGE(默认 2 周)定义的时长过期。这会覆盖登录时的 Remember me 复选框。"
Cookie 是否持久化的判断逻辑位于 src/metabase/request/cookies.clj 的use-permanent-cookies?函数:
- 若
MB_SESSION_COOKIES已设置,一律禁用持久 Cookie(返回false); - 否则回退到登录请求体中的
remember字段,即用户是否勾选了 Remember me。
结合 src/metabase/request/cookies.clj 的set-session-cookies可以看到:只有当启用持久 Cookie 时,响应才会附带Max-Age指令;没有Max-Age和Expires的 Cookie 属于会话 Cookie,浏览器关闭即被删除。同时,正常会话 Cookie 会附加HttpOnly、SameSite(默认lax)等属性,HTTPS 请求下还会附加Secure标志。
浏览器"会话恢复"的例外
需要留意:许多浏览器支持**会话恢复(session restore)**功能——启动时自动重新打开上次的标签页。当会话恢复处于启用状态时,浏览器表现得像从未关闭过一样,会话 Cookie 会跨浏览器重启持续存在。这一点通常可以在浏览器设置中配置,因此MB_SESSION_COOKIES=true的实际效果取决于终端用户的浏览器行为,无法被服务端完全强制。
三个配置的完整对照
| 配置项 | 作用 | 类型/单位 | 默认值 | 配置位置 | 版本要求 |
|---|---|---|---|---|---|
MAX_SESSION_AGE | 绝对会话寿命上限 | 整数(分钟) | 20160(14 天) | 仅环境变量 | 所有版本 |
MB_SESSION_TIMEOUT | 不活跃超时登出 | JSON,单位支持 seconds/minutes/hours | 未配置(不启用) | 管理界面(仅分钟/小时)或环境变量(含秒) | 付费版(EE) |
MB_SESSION_COOKIES | 强制使用会话 Cookie,关闭浏览器即登出 | 布尔值 | false | 环境变量 | 所有版本 |
配置建议与验证方式
什么时候用哪种?可以参考以下思路:
- 合规驱动的固定周期重新认证(如每 24 小时)→
MAX_SESSION_AGE; - 安全敏感的共享设备、无人值守终端 →
MB_SESSION_TIMEOUT(配合MAX_SESSION_AGE兜底); - 公共电脑或访客场景,希望"关掉浏览器就登出"→
MB_SESSION_COOKIES=true。
如何验证配置生效?配置完成后,可观察以下可验证信号:
- 会话 Cookie 的
Max-Age与metabase.TIMEOUTCookie 的Expires值(见 src/metabase/request/cookies.clj 的set-session-timeout-cookie,该 Cookie 在每次请求时按请求时间重新计算过期时刻); - Metabase 日志中 SessionCleanup 任务的执行记录,以及应用数据库
core_session表中被清理的行数; - 接口层可通过管理后台 API(
PUT /api/setting/session-timeout)设置超时,非法值(如负数、超 100 年)会返回 HTTP 400,对应的校验测试覆盖在 test/metabase/request/settings_test.clj。
综上,会话过期配置的核心要点可以概括为:MAX_SESSION_AGE划定会话的绝对寿命,MB_SESSION_TIMEOUT治理不活跃会话,MB_SESSION_COOKIES约束关闭浏览器这一动作——三者各司其职又彼此兜底,构成了 Metabase 完整的会话生命周期管理方案。
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考