如何在多租户应用程序中使用 Meilisearch
在本教程中,您将学习如何利用 Meilisearch 提供的租户令牌功能。我们将使用 Meilisearch Javascript SDK 创建一个应用程序,该应用程序将使用租户令牌来限制对数据的访问,具体取决于不同的用户名。
**什么是多租户?**
在软件开发中,多租户意味着多个用户(也称为租户)共享相同的计算资源,但对系统范围的数据具有不同的访问权限。在 Meilisearch 中,您可能有一个索引包含属于多个不同租户的数据。在这种情况下,您的租户必须只能搜索自己的文档。
您可以使用租户令牌来实现此目的。
租户令牌
租户令牌是加密数据的小型包,可证明用户可以访问特定索引。它们包含安全凭据和有关允许用户查看该索引中的哪些文档的说明。
租户令牌的主要用例是根据用户权限强制执行限制。
用户可以使用 Meilisearch SDK 或 自定义代码生成租户令牌。
租户令牌不需要您配置任何特定的实例选项或索引设置。它们也应该是短期的—Meilisearch 不存储也不跟踪生成的令牌。
使用 SDK 生成租户令牌时,您需要四个参数
- 搜索规则:搜索规则是一组指令,定义了将在使用特定租户令牌进行的每个查询中强制执行的搜索参数。
- API 密钥:令牌可以访问与用于生成它的 API 密钥相同的索引。
- API 密钥 uid:用于生成令牌的 API 密钥的 uid 允许检查使用的 API 密钥是否有效。
- 到期日期(可选):租户令牌的到期日期
您可以在文档中阅读有关租户令牌有效负载的更多信息。
**要求**
**创建租户令牌**
可以使用 Meilisearch Javascript SDK 中提供的 generateTenantToken
函数创建租户令牌。
这是一个使用 Meilisearch SDK 创建租户令牌的简单示例
client = new Meilisearch({ host: "<https://127.0.0.1:7700>", apiKey: "masterKey", }); // We have created a Meilisearch instance in JavaScript and we will use this to create the tenant token. const apiKey = "rkDxFUHd02193e120218f72cc51a9db62729fdb4003e271f960d1631b54f3426fa8b2595"; const apiKeyUid = "85c3c2f9-bdd6-41f1-abd8-11fcf80e0f76"; const expiresAt = new Date("2025-01-01"); // Now we have declared the API Key, its uid, as well as the expiration date for the token. searchRules = { "*": { filter: "user_id = 1", }, }; // Here we have defined the search rules that will apply restrictions on the search results. tenantToken = client.generateTenantToken(apiKeyUid, searchRules, { expiresAt: expiresAt, apiKey: apiKey, }); // Now the generateTenantToken function will create a tenant token and Meilisearch can validate this token with the apiKey.
当 Meilisearch 收到带有租户令牌的搜索查询时,它会对其进行解码并将搜索规则应用于搜索请求。
应用程序用法
假设我们在 Meilisearch 实例中有一个医疗记录系统,其索引为 patient_medical_record
。此索引包含患者列表及其详细信息。我们可以使用租户令牌来限制对此数据的访问。
示例数据集
[ { "patient": "John", "description": "John is in room number 2 and is suffering from Covid", "roomNumber": 1, "isDoctorAppointed": true }, { "patient": "Zia", "description": "Zia is in room number 3 and is suffering from Dengue", "roomNumber": 2, "isDoctorAppointed": true }, { "patient": "Kevin", "description": "Kevin is in room number 4 and is suffering from Typhoid", "roomNumber": 3, "isDoctorAppointed": false } ]
在上述数据集中,我们有三名患者:John、Zia 和 Kevin。目的是限制 Zia 访问 Kevin 和 John 的数据。要实现此目的,我们需要为她创建一个带有搜索规则集的租户令牌。
在这种情况下,搜索规则可以指定为
"searchRules": { "patient_medical_record": { "filter": "patient = Zia" } }
Zia 的租户令牌将在搜索请求时应用,这将返回
[ { "patient": "Zia", "description": "Zia is in room number 3 and is suffering from Dengue", "roomNumber": 2, "isDoctorAppointed": true } ]
这是一个简单的用例,但我们可以修改规则以满足更复杂的要求。
**在您的应用程序中集成多租户功能**
我们将使用上面的示例创建一个应用程序,用于在 Meilisearch 索引中显示患者。然后,我们将使用多租户来限制对此数据的访问。
-
下载应用程序
从 Github 上的 Meilisearch 教程存储库中克隆演示应用程序的样板代码。
使用以下命令
git clone https://github.com/meilisearch/tutorials
样板代码位于 src/tenant-token-tutorial
目录中。
cd src/tenant-token-tutorial
此代码包含一个以 React.js
构建的前端应用程序和一个以 Express.js/Node.js
构建的后端服务器。
-
启动 Meilisearch
有多种方法可以下载并运行 Meilisearch 实例。运行 Meilisearch 实例的最简单方法是使用Meilisearch Cloud,它提供 14 天免费试用,无需信用卡。Meilisearch 是开源的,在此演示中,我们将使用 Docker 在本地运行它
docker pull getmeili/meilisearch:v1.0 docker run -it --rm -p 7700:7700 -e MEILI_MASTER_KEY='masterKey' -v $(pwd)/meili_data:/meili_data getmeili/meilisearch:v1.0 meilisearch --env="development"
启动 Meilisearch 时,不要忘记像上面显示的那样定义一个主密钥。它将创建生成租户令牌所需的 API 密钥。
Meilisearch 实例将在 IP 地址上运行:https://127.0.0.1:7700
。
-
向 Meilisearch 添加数据
基本目录的
seed
文件夹中有一个data.json
文件,其中包含 10 名患有多种疾病的患者列表,其中有 100 个条目,每个条目都有房间号和一些患者详细信息。我们将把信息输入到 Meilisearch 中。将终端目录更改为
seed
文件夹,并使用以下命令将给定数据添加到 Meilisearch 实例中
npm install # This command will install node dependencies npm start # This command will add all the data from data.json to Meilisearch
-
启动前端服务器
导航到
frontend
文件夹,并安装所有应用程序依赖项和 Meilisearch Javascript SDK
npm install # To install all the react application dependency npm install meilisearch # To install the Meilisearch SDK
安装项目的所有依赖项可能需要一段时间。
让我们使用命令启动并运行前端 React 服务器
npm start
该应用程序将在 IP 地址上运行:https://127.0.0.1:3000
。
-
添加创建租户令牌的功能
导航到
backend
文件夹并使用以下命令安装所有依赖项
npm install
在 backend
文件夹中,打开 index.js
文件。它包含 API 的路由和逻辑。
已经定义了一个用于生成租户令牌的端点
app.get("/create-tenant-token", async (req, res) => { const { value: patientName } = req.query; /* Add functionality to create Tenant token */ });
现在,我们将把功能添加到函数中的注释下面。
我们需要 API 密钥、搜索规则和过期日期才能生成租户令牌。
可以从 Javascript SDK 中的 getKeys
方法获取 API 密钥。getKeys
方法返回一个 API 密钥列表,我们可以从中选择一个用于租户令牌生成过程。为此,请将以下代码添加到上述 API 方法中
const { results } = await client.getKeys(); const apiKey = results.filter( (res) => res.name === "Default Search API Key" )[0].key; const apiKeyUid = results.filter( (res) => res.name === "Default Search API Key" )[0].uid;
我们还可以使用 createKey
函数生成新的 API 密钥。
您可以在Meilisearch 文档中阅读有关 API 密钥的更多信息。
通过指定搜索规则,我们现在可以生成有效负载。使用以下代码定义有效负载
const payload = { patient_medical_record: { filter: `patient = ${patientName}`, }, };
如果我们希望令牌在一年后过期,我们可以在创建令牌时设置过期日期,如下所示。
const expiresAt = new Date( new Date().setFullYear(new Date().getFullYear() + 1) );
要生成令牌,我们现在可以使用 Meilisearch Javascript SDK 中的 generateTenantToken
函数,并使用 res.json(
) 函数返回生成的令牌。
const tenantToken = client.generateTenantToken(apiKeyUid, payload, { apiKey, expiresAt, }); return res.json({ token: tenantToken });
这是应如何实现端点
app.get("/create-tenant-token", async (req, res) => { const { value: patientName } = req.query; /* Add functionality to create Tenant token */ const { results } = await client.getKeys(); const apiKey = results.filter( (res) => res.name === "Default Search API Key" )[0].key; const apiKeyUid = results.filter( (res) => res.name === "Default Search API Key" )[0].uid; const payload = { patient_medical_record: { filter: `patient = ${patientName}`, }, }; const expiresAt = new Date( new Date().setFullYear(new Date().getFullYear() + 1) ); const tenantToken = client.generateTenantToken(apiKeyUid, payload, { apiKey, expiresAt, }); return res.json({ token: tenantToken }); });
前端请求的端点将如下所示
https://127.0.0.1:5001/create-tenant-token?value=John
使用 API 中的值 John
创建一个包含搜索规则的有效负载。
让我们使用 npm start
命令启动 express API 服务器。服务器将在 https://127.0.0.1:5001
上运行。
-
将您的 API 与前端代码连接
在文本框中输入患者的姓名。提交输入表单后,API 调用将发送到后端,后端应返回一个租户令牌。当我们需要有关特定患者的数据时,我们可以将此令牌传递给 Meilisearch 实例。
现在必须配置前端代码以从服务器请求租户令牌。我们将使用axios 库从我们开发的
/create-tenant-token
API 获取令牌,并且我们将在 API 的参数中传递患者姓名。在
/src/utils
文件夹中打开文件index.js
,并查找getTenantToken
函数。此函数向服务器发出请求并接收返回的租户令牌。将以下代码添加到 getTenantToken 方法
export const getTenantToken = async (patientName) => { const response = await axios({ url: `${apiHost}/create-tenant-token`, method: "GET", params: { value: patientName, }, }); return response.data.token; };
-
测试已实现的功能
让我们测试一下实现;首先单击
创建租户令牌
按钮。在给定的文本框中键入名称
Kevin
,然后单击创建租户令牌
按钮。这将生成租户令牌。Meilisearch 将根据患者提供的租户令牌获取数据,在此过程中充当身份验证器。
结论
我们已经根据患者姓名限制了对医疗记录的访问。借助 Meilisearch 的多租户功能,我们可以轻松地实现这一切。这是一个很基本的用例场景。该功能可以根据您的需要变得非常复杂。例如,我们可以在电子银行应用程序中实施多租户,其中中央机构是银行,客户是租户,可以访问不同的银行账户。
如果您有任何问题,请加入我们的 Discord。有关 Meilisearch 的更多信息,请查看我们的 Github 存储库 和我们的官方 文档。