Metabase Full App Embedding 深度实战:iframe 嵌入、SSO/JWT 认证、SameSite 跨域与安全加固
Metabase Full App Embedding 深度实战iframe 嵌入、SSO/JWT 认证、SameSite 跨域与安全加固【免费下载链接】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/metabaseMetabase 的 Full app embedding全应用嵌入源码中对应enable-embedding-interactive设置允许把整个 Metabase 应用放进你的 Web 应用的 iframe 中并与你的权限体系、SSO 单点登录打通让最终用户以“你应用里的身份”查询、下钻数据。本文基于仓库中 full-app-embedding 官方文档 完整展开从授权 Origin 配置、iframe 的两种指向方式直接 URL 与/auth/sso认证端点、跨域 SameSite cookie 配置到 postMessage 双向通信协议与 UI 组件显隐控制并结合源码说明每个配置项在 Metabase 服务端的真实落点帮你在自己的产品中落地一个安全、可用、跨浏览器兼容的全应用嵌入。一、Full app embedding 是什么以及它的位置Full app embedding 的核心价值在于身份与权限的一体化嵌入方你的产品负责登录Metabase 通过 SSO推荐 JWT 方案自动把用户映射到对应群组从而应用数据权限、行列级安全让用户“只看到自己该看的数据”同时保留完整的查询构建器、下钻等交互能力。文档在 full-app-embedding.md 中明确Full app embedding lets you embed the entire Metabase app in an iframe. Full app embedding integrates your permissions and SSO to give people the right level of access to query and drill-down into your data.使用前提Pre/Enterprise 许可证能力拥有 Pro 或 Enterprise 版许可证 token将人员组织进 Metabase 群组为每个群组配置权限配置 SSO使登录时自动套用权限并展示正确的数据——文档推荐优先使用 SSO with JWT如果 Metabase 与宿主应用不在同一域名本地开发 云端 Pro 实例或不同域部署需将会话 cookie 的 SameSite 选项设为none详见后文。从源码结构看这套能力由一组设置驱动。在 src/metabase/embedding/settings.clj 中可以看到enable-embedding-interactive全应用嵌入即本文主角的开关embedding-app-origins-interactive“允许这些空格分隔的 origin 以交互方式嵌入 Metabase”对应管理界面里的Authorized origins历史遗留的enable-embedding/embedding-app-origin已标记^:deprecated自 0.51.0 起弃用计划 0.53.0 移除。值得注意的实现细节make-embedding-toggle-settersettings.clj L53-L73显示任何一类嵌入开关被打开时若embedding-secret-key为空Metabase 会自动生成一个 32 字节安全随机 hex 密钥u.random/secure-hex 32。这个密钥用于对/api/embed端点请求签 JWT。同时启动阶段有check-and-sync-settings-on-startup!L255-L262若同时设置了旧版环境变量MB_ENABLE_EMBEDDING、MB_EMBEDDING_APP_ORIGIN与新版变量MB_ENABLE_EMBEDDING_SDK/_INTERACTIVE/_STATIC、MB_EMBEDDING_APP_ORIGINS_*会直接抛错只设旧变量时则自动同步到新设置并打印弃用警告。升级实例时如果两个都配了启动会失败这是一个容易踩到的坑。另外文档也提示如果你刚开始接触嵌入也可以评估 Modular embedding——它是对单个 Metabase 组件图表、仪表盘、查询构建器等做更细粒度嵌入的改进方案而全应用嵌入适合“把整个分析体验嵌进来”的场景。二、在 Metabase 中启用全应用嵌入官方文档给出的三步操作进入Admin Embedding点击Enable Full app embedding在Authorized origins下添加你要嵌入 Metabase 的网站/应用 URL例如https://*.example.com本地开发可填http://localhost:8080见快速上手指南。这里的“Authorized origins”就是上节提到的embedding-app-origins-interactive设置它以空格分隔的 origin 列表存库加密策略为:when-encryption-key-set支持*通配。与之相邻的 SDK origin 设置有更严格的校验逻辑settings.clj L165-L189setter 会先调用validate-no-localhost-when-disabled——如果服务端设置了DISABLE_CORS_ON_LOCALHOST再往 origin 里塞localhost会抛 400 异常写入前还会经过ignore-localhost过滤掉localhost:*和localhost:port因为 localhost 本来就会被放行存了反而会在重复设置时累积。从源码结构看interactive 侧目前主要依赖该过滤而 SDK 侧把 localhost 排除写进了持久化值。启用后的效果链路浏览器从已授权 origin 的页面发起的跨域请求才会被放行iframe 内的 Metabase 才能向你的 origin 发送 postMessage 并接收响应。三、在你的网站里创建 iframe两种指向方式文档full-app-embedding.md 的 “Setting up embedding on your website” 一节给出的完整步骤创建一个 iframesrc指向你要嵌入的 Metabase 页面的 URL或一个会重定向到你 Metabase URL 的认证端点可选通过环境变量完成添加许可证 tokenMB_PREMIUM_EMBEDDING_TOKEN、跨域嵌入、加固嵌入安全可选启用与嵌入实例 Metabase 的双向postMessage通信见第七节可选通过 URL 参数显示/隐藏 Metabase UI 组件。上线前必须确认访问者允许来自 Metabase 的浏览器 cookie否则无法登录。仓库自带了可直接照抄的参考实现docs/embedding/snippets/interactive-embedding-quick-start-guide/sso-with-jwt.tsNode.js Express完整快速上手流程见 full-app-embedding-quick-start-guide.md。其核心结构是// 参考实现片段来自仓库 docs/embedding/snippets/interactive-embedding-quick-start-guide/sso-with-jwt.ts app.get(/sso/metabase, restrict, (req, res) { const ssoUrl new URL(/auth/sso, METABASE_INSTANCE_URL); ssoUrl.searchParams.set(jwt, signUserToken(req.session.user)); ssoUrl.searchParams.set(return_to, req.query.return_to?.toString() ?? /); res.redirect(ssoUrl.href); }); app.get(/analytics, restrict, (req, res) { const METABASE_DASHBOARD_PATH /dashboard/entity/[Entity ID]; const iframeUrl /sso/metabase?return_to${METABASE_DASHBOARD_PATH}; res.send( iframe src${iframeUrl} frameborder0 width1280 height600 allowtransparency/iframe, ); });其中signUserToken用 Metabase 后台生成的共享密钥签发 JWTpayload 含email、first_name、last_name、groups及任意用户属性并带 10 分钟过期时间restrict辅助函数保证路由只对被登录用户开放。3.1 直接指向一个 Metabase URL先到你的 Metabase 里找到要嵌入的页面。以嵌入首页为例src设为你的 Site URLsrchttps://metabase.yourcompany.com/嵌入指定仪表盘时推荐使用 Entity ID URLsrchttps://metabase.yourcompany.com/dashboard/entity/[Entity ID]获取 Entity ID 的方法打开仪表盘点击info按钮在Overview标签中复制Entity ID例如srchttps://metabase.yourcompany.com/dashboard/entity/Dc_7X8N7zf4iDK9Ps1M3b若仪表盘有多个 Tab选择希望用户落地的 Tab 并复制 Tab ID拼到 URL 上srchttps://metabase.yourcompany.com/dashboard/entity/Dc_7X8N7zf4iDK9Ps1M3b?tabYLNdEYtzuSMA0lqO7u3FD文档特别强调可以用顺序 ID但应优先用 Entity ID——Entity ID 在不同环境间是稳定的。例如在 staging 环境测试时把数据导出再导入生产环境顺序 ID 可能变化而 Entity ID 保持不变嵌入链接不会失效。指向问题、集合、模型时同理访问对应条目、从 info 中拿到 Entity ID遵循 URL 结构/[Item type]/entity/[Entity-Id]/collection/entity/[Entity ID]/model/entity/[Entity ID]/question/entity/[Entity ID]3.2 指向认证端点SSO 直达如果你希望用户跳过 Metabase 自带登录页、直接进入你的 SSO 登录界面并在认证后自动跳回 Metabase就把src指向认证端点并用return_to参数携带编码后的 Metabase URL。例如认证后自动跳回https://metabase.yourcompany.com/dashboard/1https://metabase.example.com/auth/sso?return_tohttp%3A%2F%2Fmetabase.yourcompany.com%2Fdashboard%2F1使用 JWT 时return_to可以用相对路径即去掉 Site URL 的 Metabase 路径。例如跳到/dashboard/1https://metabase.example.com/auth/sso?jwttokenreturn_to%2Fdashboard%2F1为避免 JWT 出现在 URL 上也可以用POST请求 JSON body 的方式完成 JWT 认证细节见 JWT-based authentication。一个关键约束文档原文强调重定向链接中的所有参数都必须 URL 编码视你的 Web 栈配置可能需要二次编码包括过滤参数如filtervalue和 UI 设置参数如top_navtrue。例如给上面的 JWT 例子追加两个过滤参数后src变为https://metabase.example.com/auth/sso?jwttokenredirect%2Fdashboard%2F1%3Ffilter1%3Dvalue%26filter2%3Dvalue四、跨域嵌入与 SameSite 配置如果你的 Metabase 与宿主应用已经在同一顶层域名TLD下可跳过本节。先说浏览器兼容性总原则为了让嵌入的 Metabase 在所有浏览器都工作Metabase 与宿主应用应放在同一顶层域名TLD下即地址的最后一段如.com、.org。并且由于 iOS 上任何浏览器包括 iOS 上的 Chrome的 Web 内核都是 WebKit全应用嵌入必须兼容 Safari 才能在任意 iOS 浏览器上运行。当确实需要跨域例如 Metabase 在metabase.yourcompany.com嵌入方在yourcompany.github.io时可以让 Metabase 将会话 cookie 的 SameSite 值设为none。设置位置Admin Embedding Security SameSite cookie setting。三个取值的语义文档原文整理值行为适用场景Lax默认允许会话 cookie 在同域内共享生产环境、与 Metabase 同域的应用None要求 HTTPS允许跨站携带 cookie应用与 Metabase 托管在不同域名时使用与 Safari 及 iOS 系浏览器不兼容Strict不推荐不允许与会话嵌入实例共享 cookie仅当明确不想让嵌入方共享会话时使用也可以通过环境变量MB_SESSION_COOKIE_SAMESITE设置。这部分在源码中对应得非常清楚。src/metabase/request/settings.clj 定义了session-cookie-samesite设置合法值集合为#{:lax :none :strict nil}默认:laxsetter 会对非法值抛出带possible-values的异常src/metabase/request/cookies.clj 在生成会话 cookie 时读取该值并写入same-site属性。更值得注意的是 cookies.clj L78 附近存在一个专门的:full-app-embedcookie 属性分支default-session-cookie-attributes(defmethod default-session-cookie-attributes :full-app-embed [_ request] (merge {:path /} (when (#{:https :unknown} (request.util/https-state request)) ;; SameSiteNone is required for cross-domain full-app embedding. This is safe because ;; security is provided via anti-CSRF token. ... {:same-site :none :secure true})))也就是说Metabase 对全应用嵌入签发的会话 cookie 会强制SameSiteNoneSecure且仅在 HTTPS 或无法判定协议时才设置防止同域嵌入下非 HTTPS 请求把 cookie 拒掉源码注释明确说明安全性由防 CSRF token 兜底。这解释了文档为什么建议尽量同 TLD 部署浏览器尤其 Safari对SameSiteNone跨站 cookie 的接受度差异正是跨域嵌入兼容性问题的主要来源。如果你使用 Safari还需要在浏览器端允许跨站跟踪另外不同浏览器在隐私/无痕模式下查看嵌入内容时也可能出现问题。五、SSO 与权限让嵌入“认人”全应用嵌入的安全模型是你的应用签发身份Metabase 信任并落库。文档推荐的完整链路详见 JWT 认证文档 与快速上手Metabase 侧在Embedding设置的Authentication中完成 JWT Setup——填入你的应用 SSO 路由的JWT Identity Provider URI如http://localhost:8080/sso/metabase点击Generate key生成签名密钥注意重新生成会覆盖旧 key需要同步更新你应用里的配置然后Save and enable应用侧用共享密钥签发 JWTemail、first_name、last_name必填语义字段iframe 加载/auth/sso?jwt...return_to...完成登录。首次 SSO 登录时 Metabase 会自动创建账户群组同步JWT payload 中加入groups数组例如groups: [Customer-Acme]在Authentication JWT Edit的Group schema中打开Synchronize group memberships。若数组值与 Metabase 群组名完全一致则自动映射否则逐条添加 New mapping 做名称映射数据权限Metabase 默认“全用户All Users”群组有数据访问权且用户取其权限最宽的群组的权限。因此先重置 All Users 的数据权限例如将 Sample Database 的 View data 设为 Blocked再为每个客户群组设置 行级/列级安全。行级安全的关键机制JWT 里的任意自定义 key如account_id: 28会被 Metabase 存为用户属性之后可把表中某列与该用户属性关联实现“每人只能看到与自己账户相关的行”。多客户multi-tenant场景的群组策略文档专门给出了一种推荐的群组组织方式适合“同一客户的多人协作 跨客户数据隔离”每个客户账户建一个群组该客户的人共享一个群组用于行级/列级安全——通过某个适用于所有客户账户的统一属性设置数据权限每个人再额外加入其所在客户账户的专属群组这样同一客户组织内的人可以在 collections 中协作同时又看不到其他客户账户创建的内容。六、安全加固会话生命周期与登出Metabase 使用 HTTP cookie 完成认证并保持登录即使用户关闭浏览器会话后仍保持登录。围绕这一点有三个可调项限制登录时长设置MAX_SESSION_AGE单位分钟默认20,160两周。例如最长保持 24 小时登录MAX_SESSION_AGE1440关闭浏览器即清除登录 cookieMB_SESSION_COOKIEStrue手动登出加载登出 URL 即可可放在你应用登出页的隐藏 iframe 里实现“退出你的应用 同时退出 Metabase”https://metabase.yourcompany.com/auth/logout更完整的认证流程图可参考 securing-embeds.md 中“Full app embedding with SSO”的图示化说明。七、postMessage 双向通信协议全应用嵌入支持通过postMessage在宿主应用与 Metabase 之间通信消息体统一包在metabase键下。7.1 从嵌入的 Metabase 发出的消息宿主监听location——跟踪嵌入页 URL 变化例如应用了过滤器时可用于深链。注意它镜像window.location{ metabase: { type: location, location: LOCATION_OBJECT_OR_URL } }framenormal 模式——让嵌入页如问题页撑满整个 iframe{ metabase: { type: frame, frame: { mode: normal } } }framefit 模式——让宿主把 iframe 尺寸调整为与嵌入内容如仪表盘匹配的高度{ metabase: { type: frame, frame: { mode: fit, height: HEIGHT_IN_PIXELS } } }7.2 发往嵌入的 Metabase 的消息宿主发送location——从你的应用切换嵌入 URL{ metabase: { type: location, location: LOCATION_OBJECT_OR_URL } }实践上监听location可以把 Metabase 内导航同步回宿主 URL保持浏览器地址栏与实际页面一致、支持刷新恢复fit模式则是仪表盘嵌入避免 iframe 高度裁切的标准做法。八、控制 Metabase UI 组件的显隐通过向嵌入 URL 追加查询参数可以显示或隐藏 Metabase 界面组件完整参数表见 full-app-ui-components.md。快速上手指南给出的用法示例隐藏 logo 和顶部导航就在 SSO 重定向的return_toURL 上追加?logofalsetop_navfalse// 参考实现片段来自 docs/embedding/snippets/interactive-embedding-quick-start-guide/sso-with-jwt.ts app.get(/sso/metabase, restrict, (req, res) { const ssoUrl new URL(/auth/sso, METABASE_INSTANCE_URL); ssoUrl.searchParams.set(jwt, signUserToken(req.session.user)); // 在 return_to 上追加 UI 显隐参数 ssoUrl.searchParams.set( return_to, ${req.query.return_to ?? /}?logofalsetop_navfalse, ); res.redirect(ssoUrl.href); });主要参数摘自 full-app-ui-components.md参数默认说明top_nav显示控制整个顶部导航栏设为false时其子元素search、new_button、breadcrumbs自动隐藏side_nav仅在/collection与首页显示设为true允许用户在其他路由展开侧边导航栏search隐藏顶部导航的搜索框new_button隐藏创建查询/仪表盘的 New按钮logotrue控制侧栏 logo行为与side_nav组合决定见该文档的组合表breadcrumbs显示顶部导航中的集合面包屑路径header问题/仪表盘页显示标题、附加信息与操作按钮的容器action_buttonsheader 启用时显示Filter、Summarize、查询构建器按钮等additional_infoheader 启用时显示“Edited X days ago by …” 与数据库/表面包屑data_picker简版下拉data_pickerstaged启用完整数据选择器entity_types全部数据选择器/侧栏/New 按钮菜单中显示的实体类型table、model、question仅data_pickerstaged生效逗号分隔如entity_typestable,modellocale跟随用户界面语言如localees见本地化该文档还提示一个易被忽略的点若要在 仪表盘点击行为 跳转后保留这些查询参数需把 Site URL 管理设置配置为你的 Metabase 服务器 URL。如果需要比 URL 参数更细的组件级控制文档建议评估 Modular embedding。九、Metabot 与其他扩展点全应用嵌入中还可以启用/配置嵌入实例里的 MetabotAI 助手设置项见 Embedded Metabot settings。另外嵌入实例的外观字体、颜色、logo可通过 Customizing appearance 定制让嵌入的 Metabase 与你产品的视觉语言一致。十、排查清单与延伸阅读基于本文与仓库文档落地失败时按以下顺序自查登录不进去确认访问者浏览器允许 Metabase 的 cookie确认 origin 已加入 Authorized origins跨域时 cookie 不生效检查 SameSite 配置不同域需none HTTPSSafari 需允许跨站跟踪隐私模式可能受阻参数不生效/跳转会丢失参数检查return_to、filter、UI 参数是否全部 URL 编码必要时二次编码配置 Site URL权限不符合预期确认 JWTgroups与 Metabase 群组映射成功Admin People 里查看成员所属群组注意 Basic 用户本身看不到群组确认 All Users 群组的数据权限已被收紧环境迁移后链接失效优先使用 Entity ID URL/dashboard/entity/...避免顺序 ID。延伸阅读均为仓库内文档Full app embedding quick start——含 JWT Setup、群组同步、行级权限设置的完整分步指南与检查点Full app embedding UI components——UI 显隐参数全表与logo×side_nav组合行为Securing embeds——带图示的 SSO 认证流JWT-based authentication——/auth/sso、POST JSON body 认证、用户属性与群组同步细节Modular embedding——组件级嵌入的替代方案源码入口src/metabase/embedding/settings.clj嵌入开关与 origin 校验、src/metabase/request/cookies.clj 与 src/metabase/request/settings.clj会话 cookie 与 SameSite、docs/embedding/snippets/interactive-embedding-quick-start-guide/sso-with-jwt.ts参考实现。【免费下载链接】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),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →