Apache Superset Embedded SDK 实战:利用 Guest Token 将仪表盘安全嵌入自有应用
【免费下载链接】supersetApache Superset is a Data Visualization and Data Exploration Platform项目地址: https://gitcode.com/gh_mirrors/supers/superset
本文围绕 Apache Superset 仓库中的 superset-embedded-sdk/README.md 展开,讲解如何借助官方 Embedded SDK,通过 iframe 将 Superset 仪表盘嵌入你自己的 Web 应用,并使用 Guest Token 复用宿主应用自身的认证体系,让用户无需登录 Superset 即可查看受控数据。读完本文,你将掌握 SDK 的安装与调用、Guest Token 的签发原理、iframe 沙箱加固方式,以及 SDK 底层的通信与令牌自动刷新机制。
SDK 是什么:一句话理解嵌入原理
Embedded SDK 的核心思路非常简单:在宿主页面中动态创建一个 iframe,让 iframe 加载 Superset 内部的仪表盘页面,从而把仪表盘“镶”进你自己的应用。SDK 负责三件关键事情:
- 根据传入的配置构造正确的嵌入式仪表盘 URL(
{supersetDomain}/embedded/{dashboardId}); - 把宿主后端签发的 Guest Token 通过消息通道传递给 iframe 内的 Superset 页面,完成免登录授权;
- 提供卸载、获取滚动尺寸、获取永久链接等控制能力,方便宿主应用与嵌入式仪表盘交互。
其核心实现位于 superset-embedded-sdk/src/index.ts 中的embedDashboard函数,源码与本文后续内容一一对应。
快速开始:安装与最小调用
通过 npm 安装
SDK 以 npm 包形式发布,包名为@superset-ui/embedded-sdk:
npm install --save @superset-ui/embedded-sdk安装后在代码中引入并调用:
import { embedDashboard } from "@superset-ui/embedded-sdk"; embedDashboard({ id: "abc123", // 由 Superset 的嵌入配置界面提供 supersetDomain: "https://superset.example.com", mountPoint: document.getElementById("my-superset-container"), // 任意可容纳 iframe 的 HTML 元素 fetchGuestToken: () => fetchGuestTokenFromBackend(), dashboardUiConfig: { // 仪表盘 UI 配置:hideTitle、hideTab、hideChartControls、filters.visible、filters.expanded(可选)、urlParams(可选) hideTitle: true, filters: { expanded: true, }, urlParams: { foo: 'value1', bar: 'value2', // ... } }, // 可选:额外的 iframe sandbox 属性 iframeSandboxExtras: ['allow-top-navigation', 'allow-popups-to-escape-sandbox'] });通过 CDN 加载
也可以不经过构建工具,直接从 CDN 加载。此时 SDK 会以全局变量supersetEmbeddedSdk暴露:
<script src="https://unpkg.com/@superset-ui/embedded-sdk"></script> <script> supersetEmbeddedSdk.embedDashboard({ // ... 这里填入与上面示例完全相同的参数 }); </script>说明:SDK 当前仓库版本为
0.1.0-alpha.12(见 superset-embedded-sdk/package.json),运行时依赖@superset-ui/switchboard(iframe 消息通信)与jwt-decode(解析 Guest Token 过期时间)。
embedDashboard 参数全解
embedDashboard是 SDK 唯一的入口函数,其类型定义EmbedDashboardParams位于 superset-embedded-sdk/src/index.ts,各参数含义如下:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 仪表盘的嵌入配置 ID,由 Superset 的嵌入配置界面生成 |
supersetDomain | string | 是 | Superset 实例域名,需带协议,如https://superset.example.com |
mountPoint | HTMLElement | 是 | 用于挂载 iframe 的宿主页面 HTML 元素 |
fetchGuestToken | () => Promise<string> | 是 | 从宿主后端获取 Guest Token 的函数 |
dashboardUiConfig | UiConfigType | 否 | 仪表盘 UI 与行为配置(见下) |
debug | boolean | 否 | 是否输出调试日志,默认false |
iframeTitle | string | 否 | iframe 的title属性,默认"Embedded Dashboard" |
iframeSandboxExtras | string[] | 否 | 额外的 iframe sandbox 属性,默认[] |
dashboardUiConfig 详解
dashboardUiConfig(类型为UiConfigType,见 src/index.ts)控制嵌入后仪表盘的外观与交互:
| 字段 | 类型 | 说明 |
|---|---|---|
hideTitle | boolean | 隐藏仪表盘标题 |
hideTab | boolean | 隐藏 Tab 页签 |
hideChartControls | boolean | 隐藏图表控制(编辑类控件) |
filters.visible | boolean | 是否显示筛选器面板 |
filters.expanded | boolean | 筛选器面板是否默认展开 |
urlParams | Record<string, any> | 追加到嵌入式页面 URL 上的自定义查询参数 |
从源码(src/index.ts)可以看到这些配置最终被序列化为 URL 查询参数传给 iframe:
hideTitle、hideTab、hideChartControls通过位掩码合并为一个数字uiConfig:hideTitle记 1、hideTab记 2、hideChartControls记 8(源码 src/index.ts);filters.visible与filters.expanded分别映射为 URL 参数show_filters与expand_filters,映射表定义在 superset-embedded-sdk/src/const.ts;- 若
urlParams中的键与上述参数冲突,urlParams优先生效(见 src/index.ts 的合并顺序)。
认证与授权:Guest Token 机制
嵌入式资源使用一种特殊令牌 ——Guest Token(访客令牌)—— 来授予用户访问 Superset 的权限,而无需你的用户直接登录 Superset。整体流程为:宿主后端向 Superset 的POST /security/guest_token端点申请令牌,再把令牌传给宿主前端;前端 SDK 拿到令牌后用它完成仪表盘嵌入。
在宿主后端创建 Guest Token
宿主后端需要以 HTTPPOST方式请求/security/guest_token,请求体描述该令牌将被授予哪些资源访问权限。Guest Token 还可以携带Row Level Security(行级安全,RLS)规则,按用户动态过滤数据。
发起该请求的代理必须拥有can_grant_guest_token权限。服务端校验逻辑可在 superset/security/api.py 中查看:请求体先经GuestTokenCreateSchema校验,再校验资源存在性,最后调用create_guest_access_token生成令牌。
示例请求体:
{ "user": { "username": "stan_lee", "first_name": "Stan", "last_name": "Lee" }, "resources": [{ "type": "dashboard", "id": "abc123" }], "rls": [ { "clause": "publisher = 'Nintendo'" } ] }字段说明(与 superset/security/api.py 中的 schema 一一对应):
user(可选):用户属性,可用于图表内的 Jinja 模板,便于做个性化渲染;对应UserSchema中的username、first_name、last_name字段;resources(必填):令牌可访问的资源列表,type目前支持dashboard(枚举定义见 superset/security/guest_token.py),id为资源标识;rls(必填):行级安全规则列表,clause为过滤条件,可选dataset指定数据集编号。
令牌生效后的角色与默认配置
在宿主应用内使用 Guest Token 时,Superset 会创建一个匿名用户对象(Anonymous user)来完成认证。该访客匿名用户默认归属于公共角色,对应配置项:
GUEST_ROLE_NAME = "Public"该配置位于 superset/config.py。Guest Token 底层是 JWT,相关的服务端配置也在 superset/config.py:
| 配置项 | 默认值 | 说明 |
|---|---|---|
GUEST_TOKEN_JWT_SECRET | "test-guest-secret-change-me" | JWT 签名密钥,生产环境必须更换 |
GUEST_TOKEN_JWT_ALGO | "HS256" | JWT 签名算法 |
GUEST_TOKEN_JWT_EXP_SECONDS | 300 | 令牌有效期,默认 5 分钟 |
GUEST_TOKEN_JWT_AUDIENCE | None | JWT 受众声明,可配置为固定字符串或回调函数 |
启用嵌入式功能的特性开关
嵌入功能默认并未开启。服务端需要打开特性开关EMBEDDED_SUPERSET(默认False,见 superset/config.py)。嵌入式仪表盘的查询接口 superset/embedded/api.py 在before_request钩子中检查该开关,未开启时直接返回 404。
iframe 沙箱:默认安全模型与扩展
Embedded SDK 默认以sandbox(沙箱)模式创建 iframe,对 iframe 内内容的执行施加限制。SDK 默认添加的 sandbox 属性(见 src/index.ts)包括:
allow-same-origin:同源策略,postMessage通信所必需;allow-scripts:允许执行脚本;allow-presentation:支持图表全屏展示;allow-downloads:支持将图表下载为图片;allow-forms:允许表单提交;allow-popups:支持将图表导出为 CSV 时打开弹窗。
如需更多能力,通过iframeSandboxExtras追加额外的 sandbox 属性,例如放开顶层导航与弹窗逃逸:
iframeSandboxExtras: ['allow-top-navigation', 'allow-popups-to-escape-sandbox']源码级剖析:SDK 的底层工作机制
1. 通信通道:MessageChannel + Switchboard
iframe 加载完成后,SDK 会创建一个MessageChannel,把其中一个端口通过postMessage传给 iframe 内的 Superset 页面(消息类型常量__embedded_comms__定义在 src/const.ts),从而建立宿主窗口与 iframe 之间的双向通信,参见 src/index.ts。Switchboard(来自@superset-ui/switchboard包)在此基础上封装出类型安全的消息收发 API,Guest Token 正是通过这条通道发送给 iframe 内的仪表盘页面的。
2. Guest Token 自动刷新
Guest Token 默认有效期只有 5 分钟,因此 SDK 会在令牌临近过期时自动重新调用fetchGuestToken并再次通过消息通道下发新令牌,避免嵌入页面因令牌过期而请求失败。刷新时机的计算逻辑位于 superset-embedded-sdk/src/guestTokenRefresh.ts:
REFRESH_TIMING_BUFFER_MS = 5000:提前 5 秒刷新,避免 Superset 请求恰好落在过期瞬间;MIN_REFRESH_WAIT_MS = 10000:最小刷新间隔 10 秒,防止异常场景下高频刷新请求;DEFAULT_TOKEN_EXP_MS = 300000:当解析 JWT 的exp失败时,按 5 分钟兜底计算。
SDK 通过jwt-decode解析 JWT,兼容整数(秒)与 ISO 字符串两种exp格式(见 src/guestTokenRefresh.ts)。对应的单元测试在 superset-embedded-sdk/src/guestTokenRefresh.test.ts,覆盖了 epoch 秒、带小数的 epoch、ISO 日期、过期令牌与非法日期共五种场景。
3. 返回的 EmbeddedDashboard 控制句柄
embedDashboard返回一个 Promise,resolve 出的对象(类型EmbeddedDashboard,见 src/index.ts)提供四个方法:
| 方法 | 说明 |
|---|---|
getScrollSize() | 获取 iframe 内容可滚动尺寸{ width, height },用于自适应宿主页面布局 |
unmount() | 从mountPoint中移除 iframe,卸载嵌入式仪表盘 |
getDashboardPermalink(anchor) | 获取仪表盘指定位置的永久链接 |
getActiveTabs() | 获取当前激活的 Tab 列表 |
这四个方法都是通过 Switchboard 通道向 iframe 内的页面发起远程调用(见 src/index.ts),宿主应用可以据此实现“随仪表盘 Tab 切换而联动自身导航”“提供返回按钮时主动卸载”等产品化交互。
端到端接入清单
将以上内容串成一个完整的接入流程:
- 服务端:打开特性开关
EMBEDDED_SUPERSET = True,并设置生产环境的GUEST_TOKEN_JWT_SECRET; - 权限:为签发令牌的账号授予
can_grant_guest_token权限,并按需配置GUEST_ROLE_NAME对应的角色及其可访问资源; - 宿主后端:实现一个受你自身认证体系保护的接口,内部调用
POST /security/guest_token构造带user、resources、rls的请求体并返回令牌; - 宿主前端:安装
@superset-ui/embedded-sdk,调用embedDashboard,把fetchGuestToken指向第 3 步的接口,并传入id、supersetDomain、mountPoint; - 交互增强:按需使用
dashboardUiConfig定制 UI,用iframeSandboxExtras调整沙箱策略,用返回值中的四个方法实现卸载、滚动自适应、永久链接与 Tab 联动。
总结
Superset Embedded SDK 以“iframe 嵌入 + Guest Token 授权 + 消息通道通信”三件套,提供了一条将 Superset 仪表盘无缝接入自有产品体系的标准路径:用户认证完全复用宿主应用,数据访问通过resources与 RLS 规则精细收敛,令牌自动刷新保证了长时间使用的稳定性,沙箱默认策略则守住安全底线。若需更深入地调试或扩展,建议直接阅读 superset-embedded-sdk/src/index.ts 与 superset/security/api.py 两份核心源码。
【免费下载链接】supersetApache Superset is a Data Visualization and Data Exploration Platform项目地址: https://gitcode.com/gh_mirrors/supers/superset
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考