交互式嵌入快速入门
您将在您的应用中嵌入完整的 Metabase 应用。登录后,用户可以在您的 Web 应用中查看 Metabase 仪表板,并能够使用完整的 Metabase 应用来探索他们的数据,且仅限于他们的数据。
先决条件
- 您有一个可以嵌入 Metabase 的应用。
- 您拥有 Metabase 的专业版或企业版订阅。如果您不确定从何开始,请注册 本地专业版 的免费试用。如果您已安装 Docker Desktop,只需搜索“metabase-enterprise”即可找到 Docker 镜像并运行它。或者,您可以按照 这些说明 进行操作。
本指南中介绍的代码可以在我们的 示例仓库 中找到。
在 Metabase 中设置 SSO 和交互式嵌入
准备好要嵌入的仪表板
您首先需要一个要嵌入的仪表板。如果您还没有,可以使用 Metabase 在新实例中包含的示例仪表板,或者使用 X 射线生成一个。
访问该仪表板并记下其 URL,例如 /dashboard/1-e-commerce-insights
。您需要将此相对 URL 放入您的应用中,因为您将使用该仪表板作为登录用户访问您应用中分析部分时看到的第一页。仅包含 ID 而省略 URL 的其余部分就足够了,例如 /dashboard/1
。
您也可以使用仪表板的 实体 ID。在仪表板上,点击信息按钮。在概览选项卡中,查找仪表板的实体 ID。复制该实体 ID。您将在 iframe 的 src
URL 中使用该实体 ID:(例如,src=/dashboard/entity/[实体 ID]
)。
启用交互式嵌入
在 Metabase 中,点击右上角的齿轮图标,然后转到管理设置 > 设置 > 嵌入。找到交互式嵌入并点击已启用切换按钮。
点击交互式嵌入下的配置按钮。在授权来源下,添加您要嵌入 Metabase 的网站或 Web 应用的 URL。如果您在本地运行您的应用,您可以添加 localhost 并指定端口号,例如 https://:8080
。
SameSite 配置
如果您将 Metabase 嵌入到不同的域中,您可能需要将 会话 Cookie 的 SameSite 值设置为 none
在 Metabase 中使用 JWT 设置 SSO
启用 JWT 身份验证
仍在管理面板的设置部分中,点击身份验证。
在显示 JWT 的卡片上,点击设置按钮(您可能需要向下滚动才能看到 JWT 卡片)。
设置 JWT 身份提供者 URI
在您的应用中,您将为 SSO 创建一个路由 /sso/metabase
。在 JWT 身份提供者 URI 字段中,输入您的 SSO 路由的 URL。例如,我们的示例应用在端口 8080 上运行,因此在这种情况下,此 JWT 身份提供者 URI 可以是 https://:8080/sso/metabase
。
生成 JWT 签名密钥
点击生成密钥按钮以生成签名密钥。请保密此密钥。您将在服务器上使用它。如果您生成另一个密钥,您将覆盖现有密钥,因此您也需要更新应用中的密钥。
复制此密钥,因为您将在下一节中使用它。
保存并启用 JWT 身份验证
我们稍后将设置组同步,但现在,请务必点击保存并启用按钮以激活 JWT 身份验证。
在您的应用服务器中设置 JWT 的 SSO
将签名密钥和 Metabase 站点 URL 添加到您的应用中
在这里,您需要输入一些值才能使 SSO 工作。
您将需要在您的应用中声明两个常量
METABASE_JWT_SHARED_SECRET
,在此处粘贴您从 Metabase 获取的 JWT 签名密钥。METABASE_SITE_URL
,它指向您的 Metabase 的根路径。
const METABASE_JWT_SHARED_SECRET = "YOURSIGNINGKEY";
const METABASE_SITE_URL = "https://your-domain.metabaseapp.com";
签名密钥最好设置为环境变量,以避免意外地将密钥提交到您的应用仓库。
将 JWT 库添加到您的应用服务器
将 JWT 库添加到您的应用。例如,如果您使用带有 JavaScript 的 Node 后端,我们建议使用 jsonwebtoken。
在您的终端中
npm install jsonwebtoken --save
在您的应用中,引用该库
import jwt from "jsonwebtoken";
限制对某些路由的访问
您的应用可能已经有某种方式来确保某些路由只能在登录后访问。我们的示例使用一个名为 restrict
的简单辅助函数来保护这些路由
function restrict(req, res, next) {
if (req.session.user) {
next();
} else {
req.session.returnTo = req.originalUrl;
req.session.error = "Access denied!";
res.redirect("/login");
}
}
添加一个函数来签署用户
我们需要编写一个函数来使用 JWT 库签署用户 JWT。
const signUserToken = (user) =>
jwt.sign(
{
email: user.email,
first_name: user.firstName,
last_name: user.lastName,
exp: Math.round(Date.now() / 1000) + 60 * 10, // 10 minute expiration
},
METABASE_JWT_SHARED_SECRET,
);
添加一个 sso/metabase
路由
您需要添加一个路由,以使用 JWT 通过 SSO 将用户登录到 Metabase。如果用户尚未登录您的应用,您的应用应通过您的登录流程将其重定向。在下面的代码中,此检查和重定向由我们之前介绍的 restrict
函数处理。
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);
});
如果用户以前从未登录过 Metabase,Metabase 将为他们创建一个帐户。
检查点:使用 SSO 登录您的 Metabase
确保您已从 Metabase 注销。从 Metabase 登录页面,点击“使用 SSO 登录”。您应该被重定向到您的应用。
登录您的应用。您的应用应将您重定向到您的 Metabase 欢迎页面。如果用户尚未拥有 Metabase 帐户,Metabase 应该为他们创建一个帐户。
将 Metabase 嵌入您的应用
现在将 Metabase 嵌入您的应用。您需要设置一个路由来提供您的嵌入式分析。我们称之为 /analytics
。请注意,我们正在使用 restrict
辅助函数(如上所述),因为此页面只有在用户登录您的应用后才能查看。
在此路由中,我们需要渲染一个 iframe 来加载您的 Metabase。iframe 的 src
属性应指向您的应用 SSO 端点的相对路径。一旦用户登录您的应用(从而登录您的 Metabase),我们添加查询字符串参数 return_to
,以便 iframe 显示请求的仪表板。
METABASE_DASHBOARD_PATH
应该指向您在本指南开头创建的仪表板的相对路径(/dashboard/[ID]
,或者如果您使用了仪表板的实体 ID:/dashboard/entity/[Entity ID]
)。
app.get("/analytics", restrict, (req, res) => {
const METABASE_DASHBOARD_PATH = "/dashboard/entity/[Entity ID]"; // e.g., `/dashboard/1` or `/dashboard/entity/nXg0q7VOZJp5a3_hceMRk`
const iframeUrl = `/sso/metabase?return_to=${METABASE_DASHBOARD_PATH}`;
res.send(
`<iframe src="${iframeUrl}" frameborder="0" width="1280" height="600" allowtransparency></iframe>`,
);
});
METABASE_DASHBOARD_PATH
只是用户登录时首先看到的内容,但您可以将该路径设置为任何 Metabase URL。由于您正在嵌入完整的 Metabase,用户将能够钻取数据并查看其他问题、仪表板和集合。
检查点:在您的应用中查看 Metabase 仪表板
使用您的应用的人员现在应该能够访问 /analytics
并查看您嵌入的 Metabase 仪表板。
如何测试:登录您的应用并访问 /analytics
路由。您应该会看到 Metabase 仪表板。
如果您使用 Safari 浏览器,并且您从不同的域提供 Metabase 和您的应用,您可能需要前往 Safari 设置并关闭 阻止跨网站跟踪。
在 Metabase 中设置群组
现在您已经设置了 SSO 和交互式嵌入,是时候设置群组,以便您可以对嵌入的 Metabase 实体(问题、仪表板、集合等)应用权限了。
向您的令牌添加一个 groups
键
回想一下用于创建 JWT 的 signUserToken
函数。向已签名的令牌添加一个映射到数组的 groups
键。Metabase 将查看该数组中的值,以查看是否有任何值映射到 Metabase 中的群组(我们稍后将逐步介绍群组映射)。
const signUserToken = (user) =>
jwt.sign(
{
email: user.email,
first_name: user.firstName,
last_name: user.lastName,
groups: ["Customer-Acme"],
exp: Math.round(Date.now() / 1000) + 60 * 10, // 10 minute expiration
},
METABASE_JWT_SHARED_SECRET,
);
在 Metabase 中创建群组
在 Metabase 中,点击齿轮图标,然后转到管理设置 > 人员 > 群组。点击创建群组按钮。添加一个与您应用中的群组对应的群组。如果您使用的是示例应用,请添加一个名为 Customer Acme
的群组。
在 Metabase 和您的应用之间同步群组
您将把 groups
键中的此字符串映射到 Metabase 群组,这样当用户通过 SSO 登录时,Metabase 会自动将他们分配到相应的 Metabase 群组。
在 Metabase 的管理部分,转到设置 > 身份验证。滚动到 JWT 卡片并点击编辑。
在群组模式部分,打开同步群组成员资格。如果 groups
数组中的群组名称与 Metabase 群组名称完全匹配(例如,都是 "Customer Acme"
),那么群组将自动映射。
如果 JWT 群组名称和 Metabase 群组名称不匹配,那么对于您要同步的每个群组,请添加一个群组映射。当您点击新建映射时,输入“Customer-Acme”,即您在 JWT 有效负载中 groups
数组中包含的字符串。然后您可以将该群组名称与我们之前创建的 Metabase 群组“Customer Acme”关联起来。
务必保存更改。
检查点:验证 Metabase 在用户登录时是否将他们分配到群组
首先,注销 Metabase 并使用 SSO 登录。
然后注销并以管理员身份登录您的 Metabase,然后转到管理设置 > 人员部分,并验证 Metabase 是否已将此人添加到相应的群组中。
注意:只有 Metabase 管理员和群组管理员知道群组。普通用户没有群组概念,也无法知道他们属于哪些群组。
设置权限
现在对该群组应用权限,以便人们只能看到特定于其帐户的数据。
重置“所有用户”组的权限
Metabase 附带两个初始组:“管理员”和“所有用户”。默认情况下,Metabase 授予“所有用户”组访问已连接数据源的权限。由于 Metabase 授予用户其最宽松组的特权,因此您需要限制“所有用户”组在将其添加到对数据源和集合具有有限或无访问权限的组之前可以看到的内容。
要重置“所有用户”组的权限,请点击齿轮图标并转到管理设置 > 权限。在数据选项卡下,转到组并选择所有用户。对于查看数据列中的示例数据库,选择“已阻止”。点击保存更改,将弹出一个模态窗口,总结您正在更改的内容。点击是。
允许查看自动生成的仪表板集合
仍在权限选项卡中,点击集合子选项卡,然后点击自动生成的仪表板集合,并将所有用户组的集合访问权限设置为查看。
点击保存更改,然后点击是。
向令牌添加用户属性
您可以在 JSON Web Token 中包含用户属性。Metabase 将从 JWT 有效负载中获取任何键并将其存储为用户属性。除了其他用例之外,您还可以使用这些用户属性来设置表上的行级权限,以便人们只能看到与其帐户相关联的结果。
如果您使用的是我们的示例应用,请通过添加键 account_id
和值 28
来编辑用于创建 JWT 的 signUserToken
函数。
const signUserToken = (user) =>
jwt.sign(
{
email: user.email,
first_name: user.firstName,
last_name: user.lastName,
// hard-coded account ID added to this object
// just to test sandboxing with Metabase's Sample Database: Invoices table
account_id: 28,
groups: ["Customer-Acme"],
exp: Math.round(Date.now() / 1000) + 60 * 10, // 10 minute expiration
},
METABASE_JWT_SHARED_SECRET,
);
该用户 ID 将对应于示例数据库“发票”表中的“帐户 ID”列。我们将在“发票”表上使用此 account_id
用户属性进行行和列安全,以便人们只能在该表中看到与其帐户 ID 相关联的行。
请注意,要将用户属性保留在 Metabase 中,您需要登录。以非管理员身份登录您的应用,然后访问包含嵌入式 Metabase 的页面。
设置行级权限
在 Metabase 中,转到管理设置 > 权限。在左侧的数据选项卡下,点击一个组。对于“示例数据库”,将其数据访问列更改为精细。
Metabase 将显示数据库中的表列表。接下来,将“发票”表的查看数据访问更改为行和列安全。
接下来,Metabase 将弹出一个模态窗口,提示您将该表中的列与用户属性关联起来。
勾选按表中的列过滤选项,并将“发票”表中的“账户 ID”列与用户属性 account_id
关联起来。(请注意,Metabase 只有在用户之前通过 SSO 登录后才会显示用户属性。)
点击保存以确认您的选择。然后点击右上角的保存更改按钮。
Metabase 会询问您是否确定要执行此操作。您确定。
检查点:查看安全仪表板
请确保您已注销之前的会话。
登录您的应用,导航到 /analytics
。仪表板现在将显示不同的信息,因为此用户只能看到部分数据。点击左侧导航底部的浏览数据。查看您安全的发票表,您应该只能看到该表中与该用户账户相关的行。
隐藏 Metabase 元素
您可以决定 显示或隐藏各种 Metabase 元素,例如是否显示导航栏、搜索或+新建按钮等等。
例如,要隐藏嵌入式 Metabase 的徽标和顶部导航栏,您需要将查询字符串参数 ?logo=false&top_nav=false
附加到您包含在 SSO 重定向中的 return_to
URL 中。
在您的 /sso/metabase
路径的处理程序中,添加查询参数
ssoUrl.searchParams.set(
"return_to",
`${req.query.return_to ?? "/"}?logo=false&top_nav=false`,
);
检查点:验证隐藏的 UI 元素
再次注销并登录您的应用,然后导航到 /analytics
。您的嵌入式 Metabase 不应包含徽标或顶部导航。
后续步骤
您可以 自定义 Metabase 在您的应用中的外观:字体、颜色和徽标。
阅读其他版本的 Metabase 的文档。