Metabase 嵌入(Embedding)完全指南:模块化嵌入、全应用嵌入与 SSO/Guest 认证选型
【免费下载链接】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 不仅可以作为团队内部使用的 BI 工具,还可以作为嵌入式分析(Embedded Analytics)引擎,把图表、看板乃至整个 Metabase 应用嵌入到你自己的网站或产品中。本文以官方 Embedding introduction 为主体骨架,系统讲解两种嵌入方式(模块化嵌入与全应用嵌入)、两种认证模型(SSO 与 Guest)的选型对比,并结合当前仓库的后端源码(JWT 验签实现 与 嵌入相关设置)深入剖析其底层原理。读完本文,你将能够根据自身场景(SaaS 多租户、客户自助分析、一次性公开分享)选出正确的嵌入方案与认证方式,并看懂 Metabase 服务端是如何校验嵌入请求的。
嵌入是什么:把 Metabase 变成你应用的一部分
Metabase 支持把**表格、图表、仪表盘、AI 对话,甚至是查询构建器(Query Builder)**嵌入到你的网站或应用程序中。本质上,嵌入就是把 Metabase 的数据分析能力以组件或完整应用的形式复用出去,让最终用户不必离开你的产品就能看数、查数。
根据嵌入粒度不同,Metabase 提供两条主路径:
- 模块化嵌入(Modular embedding):把单个 Metabase 组件(问题、看板、AI 对话、查询构建器、集合浏览器等)嵌入到应用中,与你的产品界面无缝集成。这是官方推荐、大多数用户选择的方式。
- 全应用嵌入(Full app embedding):把整个 Metabase 应用以 iframe 形式嵌入,配合你自己的品牌样式呈现。
无论选择哪种嵌入方式,你都需要同时决定如何认证查看嵌入内容的用户。认证方式是“嵌入对象上的一个设置”,而不是第三种嵌入方式。如果只是想给任何拿到链接的人分享一张图表或看板、且不需要任何认证,可以直接使用公开链接与公开嵌入(Public links and embeds)。
模块化嵌入:按需嵌入单个组件
通过模块化嵌入,你可以把 Metabase 的各个组件嵌入到自己的 Web 应用中,包括:
- 仪表盘(Dashboards)
- 问题 / 图表(Questions)
- 查询构建器(Query Builder)
- AI 对话(AI Chat)
- 集合浏览器(Collection Browser)
设置嵌入时,需要选择一种认证方式:
- Metabase 账户(SSO):适用于使用 SSO 认证的组件;
- Guest(访客):适用于使用访客认证的组件。
认证方式直接决定了用户能在嵌入里做什么(对比详见下文表格)。需要注意:一个应用页面只能使用一种认证方式,不能在同一页面混用 SSO 认证的问题和 Guest 认证的问题。
从管理后台启用模块化嵌入
在 Metabase 中进入Admin > Embedding,打开Enable modular embedding开关即可。
- 仅做 Guest 嵌入:到此就完成了,直接进入“新建嵌入”向导,或参考 Guest embedding 指南。
- 要做 SSO 认证嵌入(仅 Pro/Enterprise):还需要继续配置:
- 在Cross-Origin Resource Sharing (CORS)中添加允许嵌入 Metabase 的站点 URL(例如
https://*.example.com)。本地调试时localhost始终被包含在 CORS 策略中。 - 如果嵌入站点与 Metabase 不在同一域名,参见在不同域名中嵌入 Metabase。
- 在Cross-Origin Resource Sharing (CORS)中添加允许嵌入 Metabase 的站点 URL(例如
使用嵌入向导生成代码
Metabase 内置了嵌入向导(Embedding Wizard),你不需要手写嵌入代码:
- 访问要嵌入的内容(如某张仪表盘);
- 点击Share图标;
- 选择Embed。
也可以按Ctrl/Cmd + K打开命令面板,输入 "New embed";或进入Admin > Embedding > Modular embedding点击New embed。向导会提供实时预览,并将你的定制选项直接反映在最终生成的代码片段中。例如以下代码定义了字体、字号、背景色以及筛选器/汇总按钮的颜色:
<script> defineMetabaseConfig({ instanceUrl: "https://your-metabase-url", theme: { fontFamily: "Lato", fontSize: "16px", colors: { background: "#11123d", "text-primary": "#f9f9fc", brand: "#50e397", filter: "#7172AD", summarize: "#88BF4D", }, }, }); </script>在 OSS/Starter 计划上可以选择组件的浅色或深色主题;Pro/Enterprise 计划还可以选择已保存的主题、单独指定品牌色/文字色/背景色,并通过后续编辑代码片段启用更多高级主题选项(详见 appearance)。
生成的代码片段由三部分组成
<!-- 1. 加载嵌入库(把 URL 替换成你的 Metabase 地址) --> <script defer src="https://your-metabase-url/app/embed.js"></script> <!-- 2. 页面级全局配置 --> <script> function defineMetabaseConfig(config) { window.metabaseConfig = config; } </script> <script> defineMetabaseConfig({ instanceUrl: "https://your-metabase-url", theme: { colors: { background: "#ffffff", }, }, }); </script> <!-- 3. 被嵌入的组件及其属性 --> <metabase-question question-id="1"></metabase-question> <metabase-dashboard dashboard-id="2" with-title="false"></metabase-dashboard>- 第 1 部分:从你的 Metabase 实例加载模块化嵌入库(
/app/embed.js),注意defer属性与 Metabase URL。 - 第 2 部分:设置全局配置(如
instanceUrl、theme),该配置作用于页面上所有嵌入组件,因此同一页面只需引入一次<script>标签。 - 第 3 部分:被嵌入的组件标签及其属性。组件的完整属性清单可查阅 dashboard 组件参考、question 组件参考 与 browser 组件参考。
上述示例使用的是顺序 ID(即内容 URL 中的数字)。在 Pro/Enterprise 计划上可以改用实体 ID(Entity ID)——当你通过序列化把内容从 staging 迁移到 production 时,实体 ID 保持不变。
页面级配置(Page-level config)说明
defineMetabaseConfig()支持以下关键参数:
| 参数 | 说明 |
|---|---|
instanceUrl(必填) | 你的 Metabase 实例地址,如https://youlooknicetoday.metabaseapp.com |
theme(可选) | 嵌入内容的外观选项 |
useExistingUserSession(可选,仅开发用) | 用你的 Metabase 管理员会话在本地预览嵌入,仅支持 Google Chrome |
apiKey(可选,仅开发用) | 用 API Key 在本地预览嵌入的另一种方式 |
fetchRequestToken(可选) | 自定义 SDK 获取 JWT 刷新令牌的方式,详见自定义 JWT 认证 |
pluginsConfig(可选) | 通过handleLink等插件定制嵌入组件行为,详见handleLink插件 |
allowedCustomVisualizations(可选) | 页面上允许加载的自定义可视化,Guest 嵌入不可用 |
每个最终用户都应拥有自己的 Metabase 账户
使用 SSO 嵌入时,每个最终用户必须有独立的 Metabase 账户。如果无法为每个最终用户开户,就只能改用 Guest 嵌入。
原因很关键:如果最终用户共享一个 Metabase 账户,即使你在客户端通过模块化嵌入过滤了数据,所有用户仍持有同一个会话令牌,他们可以绕过嵌入界面直接调用 Metabase API 获取本不该看到的数据。而每个用户独立开户后,Metabase 的权限系统才能真正生效,让每个人只能看到自己有权查看的数据。共享账户也被视为不公平使用(unfair usage),模块化嵌入的公平使用方式是为每个最终用户提供独立账户。
SSO 认证嵌入的定制选项
在Admin > Embedding > Setup guide > Embed in your code创建嵌入时,Pro/Enterprise 计划可以看到以下部分或全部定制选项(对应组件属性):
- 允许在数据点上钻取(Drill-through):决定用户能否与图表交互(下钻到明细、点击筛选、缩放等)。禁用后,被嵌入的问题也会同时失去添加筛选与汇总的能力。
- 允许下载:决定用户能否下载问题结果、将看板保存为 PDF。
- 允许保存新问题:如果嵌入了查询构建器但禁用此项,用户仍可探索数据,只是无法保存。
- 参数(Parameters):为看板筛选、SQL 变量、时间分组参数设置默认值,默认值会覆盖看板/问题级别设置的默认值;还可选择是否隐藏参数。
- 显示标题(Show title):控制是否显示标题。
- 允许编辑看板与问题:让用户能在当前集合中创建/编辑看板与问题(含 SQL)。嵌入集合浏览器时勾选此项会给
<metabase-browser>设置read-only="false";<metabase-dashboard>没有等价属性,可编辑看板的嵌入方式见 Web component editable dashboard。 - 允许告警(Alerts):允许用户在嵌入的问题上创建告警,需要先配置邮件,仅适用于 SSO 认证的问题嵌入。
SSO 与 Guest 认证:如何选择
SSO 与 Guest 的能力差异决定了“能嵌入什么、用户能做什么”,下表是官方对比的完整版(✅ 支持 / ❌ 不支持):
| 功能 | SSO | Guest |
|---|---|---|
| 图表(Charts) | ✅ | ✅ |
| 仪表盘(Dashboards) | ✅ | ✅ |
| 筛选组件(Filter widgets) | ✅ | ✅ |
| 导出结果(Export results)* | ✅ | ✅ |
| 基础外观定制(Basic appearance customization)** | ✅ | ✅ |
| 行级数据隔离(Row-level data segregation) | ✅ | ✅ |
| 下钻菜单(Drill-through menus) | ✅ | ❌ |
| 查询构建器(Query builder) | ✅ | ❌ |
| SQL 编辑器 | ✅ | ❌ |
| AI 对话(AI chat) | ✅ | ❌ |
| 集合浏览器(Collection browser) | ✅ | ❌ |
| 高级多租户(Tenant)与权限(Permissions)管理 | ✅ | ❌ |
| 高级主题定制(Advanced theming) | ✅ | ❌ |
| 自定义可视化(Custom visualizations) | ✅ | ❌ |
| 使用分析(Usage analytics) | ✅ | ❌ |
| 通过插件(Plugins)定制布局与行为 | ✅ | ❌ |
| 锁定参数(Locked filters)*** | ❌ | ✅ |
* 两种认证方式默认都允许下载数据,但只有 Pro/Enterprise 计划可以关闭数据下载。 ** 无论采用哪种认证方式,都需要 Pro/Enterprise 计划。 *** 使用 SSO 的组件不需要锁定参数——因为 Metabase 知道是谁在查看,可以直接用权限来隔离数据,前期配置多一点,但长期维护成本低得多。
何时选 SSO:多租户自助分析与完整工具链
使用 SSO 时,Metabase 能识别“谁在看什么”,从而自动套用数据权限,让用户使用 Metabase 提供的全部工具的同时,只能看到自己被允许看到的数据。
SSO 的适用场景:提供多租户、自助式分析,或希望包含查询构建器、AI 对话、下钻、集合浏览器等能力。
SSO 需要 Pro/Enterprise 计划,且每个查看嵌入组件的用户都需要独立的 Metabase 账户。JWT 或 SAML 的配置详见模块化嵌入认证。如果是为多个客户提供嵌入式分析的 SaaS 产品,可以用多租户(Tenants)方案隔离各客户数据——这些被嵌入用户的账户会计入套餐计费账户数,但换来的是客户可自助查看数据、省去为每个客户定制图表的开发时间。
何时选 Guest:纯查看型的图表与看板
Guest 认证不会为查看者创建 Metabase 会话,因此无需为每个查看图表/看板的用户创建 Metabase 账户,且在所有套餐(含 OSS 和 Starter)上都可用。
“Guest”不等于“不安全”:Metabase 只有在请求携带用你的应用与 Metabase 共享的密钥签名过的 JWT时才加载组件。Guest 模式缺少的只是“身份”——没有账户可以校验权限,Metabase 无法判断一个新查询是否是当前用户被允许执行的,因此Guest 嵌入是只读(view-only)的。
Guest 的适用场景:嵌入图表和看板,且不需要临时查询或下钻能力。要按查看者过滤数据,使用锁定参数(locked parameters),由你的应用在签名令牌中设置筛选值。
Guest 嵌入的关键属性与代码
Guest 嵌入的代码分为客户端与服务端两部分。客户端配置如下:
<script defer src="YOUR_METABASE_URL/app/embed.js"></script> <script> window.metabaseConfig = { isGuest: true, instanceUrl: "YOUR_METABASE_URL", // 可选:JWT 过期后让嵌入从你的服务端获取新令牌 // guestEmbedProviderUri: "/your/apps/endpoint", }; </script> <!-- 仪表盘 --> <metabase-dashboard token="YOUR_JWT_TOKEN" with-title="true" with-downloads="false" initial-parameters='{"category":["Gizmo"]}' ></metabase-dashboard> <!-- 问题 --> <metabase-question token="YOUR_JWT_TOKEN"></metabase-question>不要把固定的 JWT 写死在 HTML 里——令牌会过期,嵌入会失效。正确做法是在服务端为每次页面加载签一个新令牌并渲染到
token属性,或配置guestEmbedProviderUri让嵌入自行获取/刷新令牌。
服务端使用 Node.js 生成签名 JWT 的示例:
const jwt = require("jsonwebtoken"); const METABASE_SECRET_KEY = "YOUR_METABASE_SECRET_KEY"; const payload = { resource: { dashboard: 10 }, // 或 { question: 5 } params: {}, exp: Math.round(Date.now() / 1000) + 10 * 60, // 10 分钟过期 }; const token = jwt.sign(payload, METABASE_SECRET_KEY);Guest 组件常用属性一览:
| 属性 | 说明 |
|---|---|
token | 必填。服务端签发的 JWT |
with-title | 显示/隐藏标题,取值"true"/"false" |
with-downloads* | 启用/禁用下载,取值"true"/"false" |
initial-parameters | 初始参数值的 JSON 字符串(非受控),如'{"category":["Gizmo"]}' |
parameters | 参数值的 JSON 字符串(受控),如'{"category":["Gizmo"]}' |
auto-refresh-interval | 仅限看板。自动刷新间隔(秒) |
custom-context | 转发给你的guestEmbedProviderUri端点的customContext,可为字符串或 JSON 字符串化对象 |
* 关闭下载仅在 Pro/Enterprise 计划上可用。
锁定参数(Locked Parameters):无账号的按人过滤
Guest 嵌入没有身份,那如何让不同用户看到不同数据?答案是锁定参数:由你的服务端在 JWT 中写入参数值,最终用户看不到也改不了筛选器,数据天然被过滤。
配置步骤:
- 在嵌入设置中把参数设为Locked;
- 在服务端把参数值放进 JWT;
- 发布该内容。
const payload = { resource: { dashboard: 10 }, params: { category: ["Gadget"], // 锁定参数值 }, exp: Math.round(Date.now() / 1000) + 10 * 60, }; const token = jwt.sign(payload, METABASE_SECRET_KEY);最终用户看不到 "category" 筛选器,但看板只会展示 "Gadget" 分类的数据。关于锁定参数,还有几个关键行为值得注意:
- 必须包含所有锁定参数:发布带锁定参数的看板/问题后,签发 JWT 时
params中必须包含锁定参数名,否则 Metabase 会拒绝请求并记录You must specify a value for :<parameter-name> in the JWT。 - 传空数组可关闭锁定:对某个令牌传
category: []可跳过该锁定筛选,便于复用同一个看板/问题并在不同上下文中条件性跳过锁定。 - 筛选名要与锁定参数名一致:重命名被用作锁定参数的看板筛选后,要同步更新 JWT
params中对应的 key;与 SQL 变量连接的锁定参数无需在服务端重命名。 - 多参数组合为 AND:多个锁定参数之间是 AND 关系;只应用其中一部分时,其余传
[]跳过。 - 锁定参数会限制可编辑参数的可选值:因为锁定参数在结果展示前就完成了过滤,同一内容上的可编辑筛选组件的下拉值也会被限制(例如锁定 State 为 "Vermont" 后,City 下拉只会出现 Vermont 的城市),无需显式联动,行为类似联动筛选。
- 与 SQL 问题的组合限制:锁定参数若连接到看板筛选、而该筛选又连接了 SQL 问题,则 JWT 中只能为该锁定参数传单个值。
用锁定参数驱动自定义筛选组件
由于 Metabase 不把锁定参数渲染为筛选组件,你可以完全自己实现筛选组件:匹配应用视觉、加入“最近使用”等自定义逻辑,或同一看板在不同位置按不同维度锁定(比如一处按 "region"、另一处按 "team")。当用户在你的自定义组件中改变取值时,在服务端用新的params重新签 JWT 并替换组件的token属性,嵌入即会携带新锁定值重新请求数据。
从服务端刷新或初始化 JWT
JWT 有exp过期时间,过期后嵌入无法加载新数据。要免刷新页面保持嵌入存活,可以配置guestEmbedProviderUri指向服务端的一个令牌端点,它支持两种流程:
- 刷新令牌:当前 JWT 即将过期时,嵌入 POST 到你的端点换取新 JWT 并替换;
- 初始化令牌(可选):如果不想在 HTML 中预渲染任何 JWT,嵌入加载时调用同一端点获取第一个令牌。
<script> window.metabaseConfig = { isGuest: true, instanceUrl: "YOUR_METABASE_URL", guestEmbedProviderUri: "/api/metabase-guest-token", }; </script>端点收到的请求体:
{ "entityType": "dashboard", "entityId": 10, "customContext": "..." }| 字段 | 说明 |
|---|---|
entityType | "dashboard"或"question" |
entityId | 组件上设置的被嵌入看板/问题的 ID |
customContext | 可选。custom-context属性设置的值 |
响应为只含jwt字段的 JSON:
{ "jwt": "YOUR_NEWLY_SIGNED_JWT" }因为请求会携带你应用的会话 Cookie,你的端点可以:拒绝未登录访问者的令牌请求(返回403);校验entityType/entityId是否对当前访问者可见(它们来自浏览器,不校验就签名等于给任何登录用户发放任意已发布内容的令牌);按访问者计算不同的params(即不同的锁定筛选值)。
不希望在 HTML 中渲染 JWT 时,可以省略token属性改用dashboard-id(或question-id),并配置guestEmbedProviderUri,嵌入会在加载时自动获取首个令牌:
<metabase-dashboard dashboard-id="10"></metabase-dashboard>如何关闭某个内容的嵌入
- 访问已发布的可嵌入问题/看板;
- 点击Share图标;
- 选择Embed→Guest embedding→Unpublish。
管理员可在Admin > Embedding查看所有已嵌入项目(Pro/Enterprise 计划在Guest embeds标签页)。另外,OSS/Starter 计划的 Guest 嵌入(图表与看板)会显示 "Powered by Metabase" 横幅,升级到 Pro/Enterprise 可移除。
Guest 嵌入的限制
由于 Guest 嵌入不创建账户,Metabase 无法获知查看者身份,因此无法享受以下能力:
- 行级与列级安全(Row and column security)
- 数据库路由(Database routing)
- 下钻(Drill-through)
- 使用分析(Usage analytics)
- 查询构建器(Query builder)
- AI 对话(AI chat)
- 自定义可视化(Custom visualizations)
需要这些能力时,请改用 SSO 模块化嵌入。此外,Guest 嵌入的看板自定义跳转目标只能使用URL选项,且每个应用页面只能使用一种认证方式(不能在同一页面混用 Guest 与 SSO)。
两种前端接入方式:Web Components 与 React SDK
无论选择哪种认证方式,模块化嵌入都提供两种接入形式:
- Web Components:一个
<script>标签加 HTML 元素(如<metabase-question>)即可。无需构建步骤、无框架依赖,可用于纯 HTML、Vue、Svelte、Rails、React 等任何前端技术栈。Metabase 的应用内向导会直接为你生成代码。 - React SDK:以 React 组件形式导入并自行组合。SDK 提供更强控制力:可以构建自定义布局,并通过插件定制行为。
如果应用基于 React 且需要更细的控制力,选 SDK;否则从 Web Components 开始即可,之后可以随时迁移到 SDK。
从仓库结构看,SDK 的产物分为两部分:轻量的@metabase/embedding-sdk-reactnpm 引导包(加载并运行主 SDK Bundle 代码),以及由 Metabase 实例直接提供的 SDK Bundle——这保证了 SDK 代码始终与其对应的 Metabase 实例兼容。相关实现位于 enterprise/frontend/src(SDK 源码目录),完整能力清单与开发指引见 SDK 文档。
全应用嵌入:iframe 中的完整 Metabase
全应用嵌入(Pro/Enterprise 计划)允许把整个 Metabase 应用嵌入 iframe,并与你的应用认证体系(SSO)集成。它整合 Metabase 的权限与 SSO,让用户以合适的数据访问级别进行查询和下钻。
如果刚开始接触 Metabase 嵌入,官方建议优先考虑模块化嵌入——它是嵌入单个 Metabase 组件时更先进、可定制性更强的方案。
全应用嵌入的前提条件
- 拥有 Pro/Enterprise 计划的 license token;
- 把人员组织进 Metabase 组;
- 为每个组配置权限;
- 配置 SSO 以自动应用权限、在登录后展示正确的数据。一般来说推荐使用 SSO with JWT。
多租户场景可参考为不同客户 Schema 配置权限的建议。如果本地运行应用且使用 Pro Cloud,或 Metabase 与应用部署在不同域名,需要把 Metabase 环境的会话 Cookie 的 SameSite 设为 "none"。
启用全应用嵌入
- 进入Admin > Embedding;
- 点击Enable Full app embedding;
- 在Authorized origins中添加嵌入 Metabase 的网站 URL(如
https://*.example.com)。
iframe 指向哪里
把 iframe 的src设为以下两者之一:
- Metabase 页面 URL:嵌入首页可设为站点 URL(如
https://metabase.yourcompany.com/)。嵌入具体看板建议使用实体 ID 形式的 URL/dashboard/entity/[Entity ID](在看板 info 按钮的 Overview 页复制 Entity ID),多标签看板还可追加?tab=[Tab ID]。实体 ID 在不同 Metabase 环境间保持稳定(staging 导出、production 导入后不变),因此优于顺序 ID。其他类型的 URL 结构同理:/collection/entity/[Entity ID]、/model/entity/[Entity ID]、/question/entity/[Entity ID]。 - 认证端点:直接把
src指向 SSO 登录页并自动重定向到 Metabase,例如https://metabase.example.com/auth/sso?return_to=<URL编码的Metabase地址>。使用 JWT 时可用相对路径:https://metabase.example.com/auth/sso?jwt=<token>&return_to=%2Fdashboard%2F1(也可用 POST + JSON body 避免把 JWT 放进 URL)。所有重定向参数(含筛选参数与 UI 设置参数)都必须做 URL 编码。
跨域名与跨浏览器注意事项
- 同 TLD 优先:为了让嵌入在所有浏览器中工作,尽量让 Metabase 与嵌入应用处于同一顶级域名(TLD)。
- 不同域名:需要在Admin > Embedding > Security > SameSite cookie setting把会话 Cookie 的 SameSite 设为 "none"(要求 HTTPS),或设置
MB_SESSION_COOKIE_SAMESITE环境变量。SameSite 取值:Lax(默认,同域共享)、None(跨域,要求 HTTPS,与 Safari/iOS 浏览器不兼容)、Strict(不推荐,禁止会话共享)。 - iOS 兼容性:全应用嵌入必须兼容 Safari 才能在 iOS 的任何浏览器(如 iOS 上的 Chrome)中运行,Safari 下需要允许跨站追踪。
保障全应用嵌入安全
Metabase 使用 HTTP Cookie 维持嵌入式会话。可配置的关键项:
MAX_SESSION_AGE:限制登录保持时长(分钟),默认 20,160(两周)。例如 24 小时:MAX_SESSION_AGE=1440。MB_SESSION_COOKIES=true:浏览器会话结束时自动清除登录 Cookie。- 手动登出:加载
https://metabase.yourcompany.com/auth/logout(例如放在应用登出页的隐藏 iframe 中)。
Metabase 与应用之间还支持双向postMessage消息:
- 从嵌入的 Metabase 发出:
location消息(URL 变化,可用于深链接)、frame消息(normal模式表示页面撑满 iframe、fit模式携带height让 iframe 匹配嵌入页面高度)。 - 发送给嵌入的 Metabase:
location消息用于改变嵌入 URL。
多客户协作的组策略
要让同一客户账号下的多人协作编辑问题与看板,需要为每个客户账号建一个组;行级/列级安全可以单独用一个贯穿所有客户账号的组来处理;客户组内的成员还可加入客户专属组,以便只在组织内共享集合、不看到其他客户的内容。更细粒度的 UI 组件显隐控制见 full app UI components;如需更细的组件级控制,仍建议使用模块化嵌入。
公开链接与公开嵌入:无认证的一次性分享
如果想把数据分享给“互联网上的任何人”,管理员可以创建公开链接(Public link)或把问题/看板直接以公开嵌入(iframe 片段)放进网页。两者本质上都不是“嵌入方案”——没有认证,任何拿到链接的人都能看到数据。
适用场景:一次性分享图表/看板,不关心谁看、希望内容对所有人可用。注意:目前无法嵌入文档(Documents),但可以创建公开文档。
AI Agent 资源
如果正在使用 AI 编码代理帮助你完成嵌入配置,可查阅 AI agent resources——其中提供了机器可读的文档与 agent skills,覆盖嵌入的安装配置、升级与迁移场景。
追踪嵌入使用情况
使用分析(Usage Analytics)会追踪嵌入使用情况,包括嵌入上下文、认证方式、主机名及其他元数据,可查看 Embedding usage 看板(Pro/Enterprise 计划)。关于嵌入组件收集的匿名使用数据,参见嵌入遥测(Embedding telemetry)。
嵌入限制速览
- 目前无法嵌入文档(Documents)(但可以创建公开文档)。
- 使用 SSO 的模块化嵌入可以渲染自定义可视化,但只能加载你加入白名单的自定义可视化;Guest 认证的组件会回退到默认可视化。
- 每个应用页面只能使用一种认证方式(SSO 或 Guest),不能混用。
原理深化:Metabase 服务端如何校验嵌入请求
理解选型之后,我们来看看仓库源码中嵌入认证的实际实现,这有助于排查问题和理解安全边界。
JWT 验签与密钥校验
嵌入请求(包括 Guest 嵌入与 SSO 嵌入)的核心都在于 JWT 验签。在 src/metabase/embedding/jwt.clj 中:
check-valid-alg会解析 JWT 的 header 并明确拒绝alg为none的令牌——防止攻击者伪造未签名令牌;同时要求 JWT 必须携带alg头。unsign使用embedding-secret-key验签:若密钥未设置则抛出 "The embedding secret key has not been set."(HTTP 400);验签时会放行60 秒时钟偏差(leeway),避免签发端与校验端时钟不同步导致误拒。get-in-unsigned-token-or-throw用于从解签后的令牌中提取必要字段(如resource、params),缺失时抛出 "Token is missing value for keypath ..."(HTTP 400)。
这解释了文档中的几个行为:为什么“必须包含所有锁定参数”(服务端会从 JWT 的params中取锁定参数值,缺失即拒绝);为什么“不要把 JWT 写死在 HTML”(令牌有过期时间,过期后unsign校验失败)。
嵌入开关与密钥设置的底层约束
在 src/metabase/embedding/settings.clj 中可以确认:
embedding-secret-key的 setter 强制校验必须是 64 字符的十六进制字符串(256 位密钥),非法值会在管理后台直接被拒绝——这对应 Guest 嵌入文档中“用你的嵌入密钥签发 JWT”的约束。- 嵌入能力拆分为多个独立开关:
enable-embedding-simple(模块化嵌入)、enable-embedding-static(静态嵌入)、enable-embedding-interactive(交互式嵌入)、enable-embedding-sdk(SDK 嵌入)。开启任意嵌入开关时,如果密钥尚未设置,会通过u.random/secure-hex 32自动生成并保存一个 256 位随机密钥。 - 旧的
MB_ENABLE_EMBEDDING与MB_EMBEDDING_APP_ORIGIN环境变量自 Metabase 0.51.0 起已废弃:启动时check-and-sync-settings-on-startup!会检测新旧设置冲突(同时设置会抛错),并在只有旧设置时自动同步到MB_ENABLE_EMBEDDING_SDK/MB_ENABLE_EMBEDDING_INTERACTIVE/MB_ENABLE_EMBEDDING_STATIC等新设置。 - 允许的来源(origins)设置会自动忽略
localhost:*/localhost:<port>(ignore-localhost),因为 localhost 始终被允许,这也印证了文档中“本地调试无需配置 CORS”的说法;同时validate-no-localhost-when-disabled会在设置了DISABLE_CORS_ON_LOCALHOST时禁止再写入 localhost 来源。
这些源码细节说明:Metabase 的嵌入体系在服务端有完整的开关、密钥与来源校验,前端向导生成的代码只是这套服务端机制的最小接入面。
进一步阅读
- 多租户(Tenants)
- 定制 Metabase 外观(Customizing Metabase's appearance)
- 保障嵌入安全(Securing embedded Metabase)
- 模块化嵌入:认证设置(Authentication)
- Guest 嵌入完整指南
- 全应用嵌入快速上手
【免费下载链接】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),仅供参考