为嵌入式 Looker 内容实现行级细分

作者:Christopher Seymour(高级数据分析师)和 Dean Hicks(开发技术推广工程师)

借助行级细分,您可以根据存储在一个或多个数据库字段中的值,限制单个用户可以访问的数据。本指南介绍了在嵌入式 Looker 内容中实现行级细分的方法,包含以下部分:

简介

Looker 的嵌入功能是 Looker 产品最强大、最有价值的功能之一。如果您正在阅读本指南,很可能您已将 Looker 内容嵌入到应用中,或者打算在不久的将来这样做。

本指南旨在帮助您更好地了解 Looker 的嵌入功能的设计,以及如何为合作伙伴可以管理多个品牌的应用实现细分。本文深入探讨了相关主题,因此篇幅较长。请注意,本指南并非旨在快速解决简单问题,而是旨在帮助您更好地管理整个 Looker 嵌入使用情形的构建块。

用例概览

本指南介绍了一种常见的使用情形:贵公司在产品中嵌入 Looker 内容,并为应看到不同数据切片的用户群提供服务。

对于此签名嵌入用例,假设您是 Looker 实例的管理员。您需要与两种类型的外部嵌入用户合作:客户(他们应只能访问与其特定品牌相关的数据)和合作伙伴(他们将能够访问多个品牌的数据)。 您有一个包含几个平铺式信息中心的界面,您会向使用您产品的每位客户显示该界面,但您需要为每位客户自动过滤该界面,以便界面仅显示特定于该客户的数据。本文档中的示例使用了两家虚构的公司,分别是 HooliPied Piper

您有一个名为 products 的表,其中显示了不同品牌的某些商品指标。每个品牌都对应于已签名嵌入应用中的不同嵌入用户(具有不同的 external_user_id)。由于每个嵌入用户都应只能看到自己品牌的数据,因此您有一个探索,该探索在 brand 用户属性上使用了访问权限过滤条件:

explore: products {
  access_filter: {
    field: products.brand
    user_attribute: brand
  }
}

您有一个基于此探索的信息中心,其中包含两个图块:一个显示品牌名称,另一个显示相应品牌的商品数量。

您可以使用 create_sso_embed_url 端点为每个嵌入用户生成相应信息中心的嵌入网址。此示例使用了两个品牌:Pied Piper 和 Hooli。以下是您在 create_sso_embed_url 调用中针对 Pied Piper 使用的请求正文,其中 external_user_idpied_piper

{
  "target_url": "https://mylookerinstance.cloud.looker.com/embed/dashboards/17",
  "session_length": 300,
  "force_logout_login": true,
  "external_user_id": "pied_piper",
  "first_name": "PiedPiper",
  "last_name": "User",
  "permissions": ["access_data","see_user_dashboards"],
  "models": ["thelook"],
  "user_attributes": {"brand":"Pied Piper"}
}

您为 Pied Piper 生成的网址会以这种方式显示信息中心:

以下是 Hooli 的 create_sso_embed_url 调用中使用的请求正文,其中 external_user_idhooli

{
  "target_url": "https://mylookerinstance.cloud.looker.com/embed/dashboards/17",
  "session_length": 300,
  "force_logout_login": true,
  "external_user_id": "hooli",
  "first_name": "Hooli",
  "last_name": "User",
  "permissions": ["access_data","see_user_dashboards"],
  "models": ["thelook"],
  "user_attributes": {"brand":"Hooli"}
}

为 Hooli 生成的网址会以如下方式显示信息中心:

就是这样!系统会根据每个嵌入用户的品牌用户属性值过滤信息中心。

深入了解

太棒了!但如果我想让单个用户访问多个品牌,该怎么办?如何确保我的数据仅供相关用户查看?

好消息!Looker 的签名嵌入功能旨在帮助开发者为用户打造强大且定制化的数据体验,同时确保数据模型和内容访问权限定义的数据治理得到维护。

确保数据治理严密无缝对于提供强大的数据体验至关重要。请继续阅读,了解一些概念和最佳实践,以便设计最适合您的体验。首先,我们简要概述一下这一切是如何运作的。

Looker 签名嵌入基础知识

请务必注意,嵌入上下文中的 Looker 用户身份验证和管理与非嵌入上下文中的 Looker 用户身份验证和管理以及大多数其他 Web 应用中的用户身份验证和管理在本质上是相同的。

在 Looker 签名嵌入上下文中,这可能会造成混淆,因为签名身份验证步骤、用户设置和信息中心本身都组合成了一个长而复杂的网址。不过,该网址用于建立会话,即使网址缩短后,此用途仍然适用。牢记这一概念将有助于您成功打造出色的数据体验。

已签名的嵌入网址结构

以下是 create_sso_embed_url 调用生成的签名嵌入身份验证网址之一,其中包含 Pied Piper 的请求正文:

https://mylookerinstance.cloud.looker.com/login/embed/%2Fembed%2Fdashboards%2F17?permissions=%5B%22access_data%22%2C%22see_user_dashboards%22%5D&models=%5B%22thelook%22%5D&signature=iG6vcKBgnA50jaL2iShFeQHwFPN7wvTx7Rz6r%2FtFuvE%3D&nonce=%22967729518a7dbb8a178f1c03a3511dd1%22&time=1696013242&session_length=300&external_user_id=%22pied_piper%22&access_filters=%7B%7D&first_name=%22Pied%22&last_name=%22Piper%22&user_attributes=%7B%22brand%22%3A%22Pied+Piper%22%7D&force_logout_login=true

下面是经过解码并拆分为单独行的同一网址:

https://mylookerinstance.cloud.looker.com/login/embed/
/embed/dashboards/17
?permissions=["access_data","see_user_dashboards"]
&models=["thelook"]
&signature=iG6vcKBgnA50jaL2iShFeQHwFPN7wvTx7Rz6r/tFuvE=
&nonce="967729518a7dbb8a178f1c03a3511dd1"
&time=1696013242
&session_length=300
&external_user_id="pied_piper"
&access_filters={}
&first_name="PiedPiper"
&last_name="User"
&user_attributes={"brand":"Pied Piper"}
&force_logout_login=true

当您访问此网址时,会发生以下情况:

  1. Looker 会查找 external_user_id = pied_piper 的现有用户账号。如果不存在,Looker 会创建具有该 external_user_id 的新用户账号。

  2. 现有用户的账号详细信息(包括权限、模型、群组 [如果已指定]、用户属性值 [如果已指定])会被网址中指定的账号详细信息覆盖。

  3. Looker 会对用户进行身份验证,并在浏览器中存储会话 Cookie,从而为该用户建立会话。

  4. 然后,Looker 会重定向到 create_sso_embed_url 调用中指定的目标网址或重定向网址:

    https://mylookerinstance.cloud.looker.com/embed/dashboards/17

    您可以在原始的已签名嵌入网址中看到此重定向网址,它是一个编码后的相对网址:

    %2Fembed%2Fdashboards%2F17

虽然第 1-3 步会在后台自动进行,并且最终用户只会看到最终结果(即信息中心本身),但这些步骤与常规的非嵌入式 Looker 用户进行身份验证的步骤基本相同。假设您希望用户使用用户名和密码凭据登录。该流程如下所示:

  1. 您(Looker 管理员)前往“管理”>“用户”面板,然后使用搜索栏查看该用户是否已有用户账号。如果没有,您需要创建一个新的用户账号。

  2. 您(Looker 管理员)在“管理”>“用户”面板中点击相应用户旁边的修改,然后为该用户配置权限、模型、群组、用户属性值和其他值。

  3. 用户前往 https://mylookerinstance.cloud.looker.com/login 的登录页面,然后输入自己的用户名和密码。Looker 会对用户进行身份验证,并在浏览器中存储会话 Cookie,从而为该用户建立会话。

  4. 然后,Looker 会重定向到着陆页(通常为 https://mylookerinstance.cloud.looker.com/browse)。

请注意,会话 Cookie 将应用于浏览器窗口中的每个标签页。如果用户从 https://mylookerinstance.cloud.looker.com/browse 开始,打开新的浏览器标签页,然后前往其权限允许访问的任何页面,该页面将使用原始浏览器标签页中已建立的会话 Cookie 正常加载。

嵌入用户也是如此。嵌入用户在界面中可以访问的页面受到更多限制,他们只能访问带有 /embed 前缀的 Look、信息中心和探索网址。不过,他们仍然可以手动导航到其用户账号详细信息授予其访问权限的任何信息中心。假设原始的已签名嵌入网址在一个浏览器标签页中将您重定向到 https://mylookerinstance.cloud.looker.com/embed/dashboards/17。然后,您打开一个新的浏览器标签页,并加载位于同一文件夹(因此具有相同的访问权限限制)中的另一个嵌入信息中心:https://mylookerinstance.cloud.looker.com/embed/dashboards/19

虽然原始签名嵌入网址中指定的重定向网址是信息中心 17,但您可以看到,如果您在浏览器标签页中手动输入该网址,信息中心 19 会按预期加载。请注意,加载其他信息中心不需要其他签名嵌入网址。

这里的重要结论是,网址中确立的所有用户账号详细信息(权限、用户属性等)都适用于整个用户会话,而不仅仅是原始签名网址中指定的特定信息中心。换句话说,顾名思义,用户属性是用户的一项功能,而不是信息中心的一项功能,它们应用于确定特定用户在整个应用中的访问权限级别,而不仅仅是在一个特定标签页中。

同时访问多个品牌

请注意,您可能还有拥有或管理多个品牌的外部合作伙伴。在此示例中,合作伙伴同时管理 Pied Piper 和 Hooli 品牌。

从非嵌入角度来看的方法

已签名的嵌入式用户会话与常规的非嵌入式 Looker 用户会话在根本上以相同的方式运作,因此,将前面描述的问题方法重新表述为常规的非嵌入式 Looker 用户会话,并分解这些步骤,有助于了解如何以更可靠的方式实现此解决方案。如果您要向有权访问 Looker 界面的标准 BI 用户提供说明,该工作流如下所示:

  1. 您可以在“管理”>“用户”页面上创建两个不同的用户账号。
    1. 在第一个用户账号的修改页面上,您将品牌用户属性值设置为 pied_piper
    2. 在第二个用户账号的修改页面上,将 brand 用户属性值设置为 hooli
  2. 您向合作伙伴发送了这两个用户账号的账号设置电子邮件。
  3. 合作伙伴为每个账号分别设置电子邮件地址和密码凭据。
  4. 您将信息中心的链接提供给合作伙伴 (https://mylookerinstance.cloud.looker.com/dashboards/17),并告知对方,如需在品牌之间切换信息中心,他们需要在另一个标签页中返回登录页面,输入其其他用户账号的电子邮件地址和密码凭据,然后在该标签页中重新加载信息中心。

合作伙伴按照说明操作。不过,在第二个浏览器标签页中输入 Hooli 用户账号的用户名和密码,然后返回到已加载 Pied Piper 信息中心的第一标签页后,合作伙伴点击了重新加载按钮。令合作伙伴惊讶的是,信息中心显示的是 Hooli 的数据!

到目前为止,您可能在想:

等等…这太不方便了。那么,实现这一目标的最佳方式是什么?

当然有!这些场景有助于说明一个原则,该原则在非嵌入式环境中已经很明确,但在嵌入式环境的抽象概念中可能会被模糊化:单个人类用户应与单个 Looker 用户账号相关联,并具有一组用户属性值。签名嵌入文档中,我们对 external_user_id 的说明也明确了这一点。

Looker 使用 external_user_id 来区分已登录的嵌入用户,因此每位用户都必须有分配给自己的唯一 ID。

您可以为用户创建任意字符串作为 external_user_id,只要该字符串对相应用户而言是唯一的即可。每个 ID 都与一组权限、用户属性和模型相关联。单个浏览器一次只能支持一个 external_user_id 或用户会话。在会话期间,无法更改用户的权限或用户属性。

同时访问多个品牌 - 不应执行的操作

与任何可自定义的解决方案一样,您应避免采用某些方法。例如,在一种实现中,您的应用使用之前显示的 create_sso_embed_url 调用中的相同输入来生成两个 external_user_ids 的网址,并在应用中创建一个新标签页来加载合作伙伴需要访问的每个信息中心。我们经常看到开发者实现这样的解决方案,但这样做会导致用户的工作流程不正确:

  1. 前往 Pied Piper 信息中心标签页。
  2. 前往 Hooli 信息中心标签页。
  3. 返回到 Pied Piper 信息中心标签页。
  4. 点击 Pied Piper 信息中心上的重新加载按钮。

…Pied Piper 信息中心显示了 Hooli 的数据!

您可能会尝试类似的方法,但对两个 create_sso_embed_url 调用使用相同的 external_user_id test_user。但行为完全相同 - 重新加载包含 Pied Piper 信息中心的标签页后,它会显示 Hooli 的数据。

如何确保每个品牌的信息中心仅显示相应品牌的数据?

运用最佳实践

如需应用“非嵌入式方法”部分中所述的方法,您需要一个用户属性值,该值可授予合作伙伴对整个应用中所有应有权访问的数据的访问权限。为此,您可以为 brand 属性使用以英文逗号分隔的值 Pied Piper,Hooli

{
  "target_url": "https://mylookerinstance.cloud.looker.com/embed/dashboards/17",
  "session_length": 300,
  "force_logout_login": true,
  "external_user_id": "test_user",
  "first_name": "Test",
  "last_name": "User",
  "permissions": ["access_data","see_user_dashboards"],
  "models": ["thelook"],
  "user_attributes": {"brand":"Pied Piper,Hooli"}
}

如需使用此语法,您需要确保将用户属性设置为字符串过滤条件(高级)

请注意,如果用户的数据访问权限级别发生变化,您仍然可以更改该用户的一组用户属性。例如,如果合作伙伴获得了第三个品牌的所有权,那么您可以将该第三个品牌添加到您为合作伙伴的品牌用户属性指定的逗号分隔列表中。这样,当他们退出账号并重新登录时,更改就会生效。

过滤信息中心结果

好的,我知道用户属性需要指定用户可以在整个应用中访问的所有数据。但是,如果我以这种方式指定用户属性,我的信息中心就会显示所有这些品牌的数据!如何将特定信息中心的结果范围缩小到特定品牌?

过滤特定信息中心的正确方法是使用常规的信息中心过滤条件!(这现在看起来可能很明显,但我们看到有些人认为用户属性是在嵌入上下文中应用过滤条件的唯一方法,这可能是因为 user_attributes 是已签名嵌入网址中的一个参数,而过滤条件不是。)

请务必要求提供过滤条件值,并使用单选控件选项之一,例如下拉菜单:

确保过滤条件已应用于所有必需的图块中的正确字段:

现在,您的合作伙伴只能选择这两个值(且只能选择这两个值),因为下拉菜单中的可用选项受用户属性的限制:

预先填充信息中心过滤条件

好的,现在可以按特定品牌过滤信息中心,但我希望用户在我的应用中加载该品牌的信息中心时,过滤条件值已设置为该特定品牌。

同样,最好先考虑一下在非嵌入式情境下,此功能是如何运作的。如何向他人发送指向已应用特定过滤条件值的信息中心的链接?您可能已经注意到,当您选择过滤条件值时,该过滤条件值会显示在信息中心的网址中:

create_sso_embed_url 调用的 target_url 中添加网址的这一部分:

{
  "target_url": "https://mylookerinstance.cloud.looker.com/embed/dashboards/17?Brand=Hooli",
  "session_length": 300,
  "force_logout_login": true,
  "external_user_id": "test_user",
  "first_name": "Test",
  "last_name": "User",
  "permissions": ["access_data","see_user_dashboards"],
  "models": ["thelook"],
  "user_attributes": {"brand":"Pied Piper,Hooli"}
}

如果您使用的是嵌入式 SDK,可以使用 withFilters 指定要应用于嵌入式内容的初始过滤条件:

https://looker-open-source.github.io/embed-sdk/classes/EmbedBuilder.html#withFilters

如果您使用的是自己的自定义脚本,则需要确保在对路径进行编码之前将过滤条件添加到网址中。某些值可能已在过滤条件字符串中进行编码(例如,?Brand=Pied+Piper 中的空格编码为 +),因此这些值将在最终网址中进行双重编码。您可以查看“SO 嵌入式信息中心 - 将信息中心过滤条件设置为网址的一部分?”Looker 社区帖子,其中讨论了这些细微差别。如果您在应用滤镜时仍遇到任何问题,也可以在该社区帖子中提出任何疑问。

隐藏信息中心过滤条件

好的,我知道如何在信息中心上设置初始过滤条件,但我也不希望合作伙伴更改信息中心过滤条件本身,过滤条件值应仅由合作伙伴在我应用中导航到的信息中心来确定。如何隐藏信息中心过滤条件?

您可以使用主题来实现此目的。主题是付费功能,因此,如果您尚未在 Looker 实例中启用此功能,则应与 Looker 销售团队联系以启用此功能。

启用该功能后,前往“管理”>“主题”页面的信息中心控件部分,您可以在其中取消选中显示过滤条件栏选项:

然后,您可以将主题设为默认主题,也可以在特定信息中心的网址中应用主题。同样,这会进入 create_sso_embed_url 调用的 target_url

{
  "target_url": "https://mylookerinstance.cloud.looker.com/embed/dashboards/17?Brand=Hooli&theme=test_theme",
  "session_length": 300,
  "force_logout_login": true,
  "external_user_id": "test_user",
  "first_name": "Test",
  "last_name": "User",
  "permissions": ["access_data","see_user_dashboards"],
  "models": ["thelook"],
  "user_attributes": {"brand":"Pied Piper,Hooli"}
}

如需详细了解如何隐藏嵌入式信息中心过滤器(包括一些嵌入式 SDK 代码段),请观看此 YouTube 教程:使用自定义过滤条件嵌入 Looker

最终结果应与原始问题中的用户体验完全相同:

但现在,由于过滤条件值已编码到嵌入应用中的相应目标网址中,因此即使您在标签页之间来回切换,每个品牌的信息中心也始终会显示过滤为相应品牌的信息中心。

以其他用户身份进行测试

现在,用户体验与我最初设想的非常接近。但在我的使用情形中,合作伙伴拥有个人用户(具有 external_user_id=pied_piperexternal_user_id=hooli)所没有的不同权限和其他用户设置,这会导致界面中显示不同的选项,并带来略有不同的整体用户体验。我想让用户看到 pied_piper hooli 用户看到的所有内容,就好像该用户实际上是以这些用户的身份登录的。如何才能做到这一点?

如果您希望用户能够以每个单独的品牌用户的身份进行测试,那么您可以在应用中构建一个类似的 sudo 函数,该函数会在用户以 Pied Piper 用户的身份进行 sudo 时加载 external_user_id=pied_piper 的嵌入网址,并在用户以 Hooli 用户的身份进行 sudo 时加载 external_user_id=hooli 的嵌入网址。如果您的应用使用该 API,您还可以使用 login_user API 端点以品牌用户的身份通过 API 进行 sudo。

不过,如果您再次考虑非嵌入式上下文:在“管理”>“用户”页面中,您无法在多个标签页中同时以多个非嵌入式用户身份执行 sudo 操作,sudo 会话将应用于整个浏览器窗口,就像所有其他用户会话一样。因此,您应将 sudo 设计为一次只能以一个用户的身份执行 sudo。如果您仔细想想,就会发现这种设计更符合完美模拟您要冒充的用户体验。例如,pied_piper 用户只能访问 Pied Piper 信息中心,而无法在其他标签页中打开其他信息中心。因此,当您以该用户的身份执行 sudo 命令时,也应该无法在不同的标签页中打开不同的信息中心。

总结

希望本指南对您有所帮助,让您能够充分做好准备,继续构建 Looker 签名嵌入内容! 我们一直在努力让 Looker 成为最灵活、最强大的嵌入式数据分析产品,并希望听到您的反馈!如果您有任何疑问或想了解更多信息,可以在 Looker 社区与我们互动,也可以参加我们的社区活动。