# 饼干授权第一部分

By [ma1984.eth](https://paragraph.com/@ma1984) · 2024-01-14

---

使用 CLI 创建 Biscuit 并检查令牌的权限。

##### **奇拉莱·穆沙哈里**

软件工程师

时空依靠饼干来支持去中心化授权。在时空平台上，饼干用于授权对资源（例如表）的访问。要了解有关《时空》中如何使用饼干的更多信息，请访问我们的[开发人员文档](https://docs.spaceandtime.io/docs/biscuit-authorization)或观看[此视频](https://www.youtube.com/watch?v=fOUR5sUbxaM&ab_channel=SpaceAndTime)。

在本教程中，我们将了解[Biscuit](https://www.biscuitsec.org/) 授权以及如何创建、授权和衰减令牌。[从此处](https://github.com/Techpro-ninja/biscuit-example)下载 GitHub 上的所有文件。

在每个平台上编写和检查授权代码通常很痛苦。Biscuit 令牌帮助我们在制作安全的微服务应用程序时节省时间和精力，因此我们不必担心跨不同服务的授权管​​理。饼干让我们可以离线制作令牌，并通过将它们以cookie的形式发送到服务器来对其进行授权。下面的图表说明了如何跨平台使用 Biscuit。

### **超长教程提醒！**

本教程是 2 个教程系列的一部分。

1.  \*\*第 1 部分：\*\*本教程涵盖 Biscuit 的基础知识、使用命令行界面 (CLI) 创建 Biscuit 以及检查令牌的权限。我们还将学习如何削弱饼干代币。
    
2.  \*\*第 2 部分：\*\*即将推出的教程。这涵盖了如何将 Biscuits 与 Golang 结合使用。
    

### **什么是 Biscuit 授权令牌？**

Biscuit 授权令牌是不记名令牌，保存有关给定应用程序的用户权限（授权）的信息。这意味着您不必为用户创建单独的授权表。Biscuit 代币的本质可以在跨多个服务器的多个应用程序的微服务架构中得到更好的理解。Biscuit 作为一种代币，可以在任何具有公钥的微服务应用程序中使用，而无需任何语言依赖。此外，Biscuits 中的权限可以扩展到新类型的用户，其权限比层次结构中的当前用户少。这个过程称为**衰减**。衰减是通过使用 Datalog（一种声明性编程语言）编写授权策略来实现的。下图说明了使用 Biscuits 的论坛网站的用例场景。

饼干离线衰减

最后，如果不想让饼干令牌进一步衰减，可以**封印**饼干。**此外，您还可以使用撤销 id**手动停用 Biscuit 令牌。

您可以将 Biscuit 代币移植到各种应用程序，并以多种编程语言实现它们。其实现所需的唯一东西是\*\*[Protobuf](https://protobuf.dev/)**生成器和**[Ed25519](https://ed25519.cr.yp.to/)\*\*签名。我们将了解如何使用 CLI 来实现 Biscuit 授权，在第 2 部分中，我们将学习如何将 Biscuits 与 Golang 结合使用。

### **饼干、智威汤逊、马卡龙**

\*\*[Biscuit 结合了 JWT 和Macarons](https://en.wikipedia.org/wiki/Macaroons_\(computer_science\))\*\*的优点，为应用程序提供最佳的授权选项，同时提供最佳的安全性。

### **Biscuit授权中的组件**

需要记住的一些重要术语：

#### **事实**

事实是数据或真理。现有事实无法更改，但可以使用规则从现有事实生成新事实（如下所述）。

例如，事实可以是：

    user("1234");
    roles(["admin", "moderator"]);
    

#### **规则**

规则可用于生成新的事实。他们接受事实作为参数，并将其与其他事实结合起来生成新的事实。

规则示例：

    rights($id, $roles) ← user($id), roles($roles);
    

该规则生成一个新事实，例如：

    rights("1234",[ "admin", "moderator"]);
    

#### **支票**

检查用于根据某些值验证事实。

例如：

    check if roles($roleList), $roleList.contains("moderator");
    

上述条件检查角色列表是否包含“**主持人**”。这些检查既可以写入 Biscuit 令牌块中，也可以在验证 Biscuit 时写入服务器端应用程序中。

#### **积木**

Biscuit 代币由块组成。每个块可以包含事实、规则和检查。默认有一个区块，称为**权限区块**。其他块是用户生成的。

#### **允许否认**

允许/拒绝条件出现在\*\*检查（\*\*如果有）之后，它们允许或拒绝对资源的访问。它们只能在授权者应用程序中使用，不能与 Biscuit 代币一起使用。

用法示例：

    allow if resource($id, $res) ← user($id), somecase($res);
    

上面的代码可以解释为，如果右侧的两个条件都满足，则只有该代码允许访问该资源。

#### **命名空间**

命名空间用于避免在微服务架构中命名事实时发生意外冲突。

    ShoppingCart:User("1234");
    AdminUSer:User("1234");
    

这里两个“**用户**”来自不同的命名空间，在编写规则时不会发生冲突。

### **尝试命令行界面 (CLI)**

Biscuit 命令行界面 (CLI) 是尝试 Biscuit 令牌的最快方法。我们将学习如何安装 CLI 并运行命令来创建、授权和衰减 Biscuit。详细命令请\*\*[访问此页面](https://github.com/biscuit-auth/biscuit-cli)\*\*。

### **安装 CLI**

您可以下载源代码或使用\*\*[Cargo 包管理器](https://doc.rust-lang.org/cargo/)\*\*来安装二进制文件。我们将遵循后者，不会专注于从源代码编译。Cargo 是 Rust 编程语言的包管理器，在本教程中它应该已经存在于您的计算机上。然后，您可以使用以下命令安装 Biscuit CLI：

    > cargo install biscuit-cli
    

_注意：您可能需要设置位于_\*/cargo/bin中的biscuit-cli\*\*的环境变量路径。**在 Ubuntu 上，您可以通过添加/etc/environment**文件的路径来设置此设置，然后运行以下命令立即使终端解析文件中的更改：\* > source /etc/environment **生成公钥/私钥对** 安装 CLI 后，您可以为您的应用程序创建基本的公钥/私钥对。服务器存储公钥，并且可以使用它来验证由私钥签名的任何令牌。例子： > biscuit keypair Generating a new random keypair Private key: 1e4a2a2453da6528a1b72ea1e7ff1b76d1e67d883a53a1671f3b5b382bc11d51 Public key: 568e1a3876a327444f18414e66714d5deb908ba0b667ca9587bf9a03df8af478 **_注意：创建名为private-key_**_和_**_public-key_**_的新文件。将上面获得的私钥和公钥分别保存到文件中。不要丢失私钥，否则您将来将无法验证您的密钥。重新生成私钥将是唯一的选择。_ **创建饼干代币** 授权文件可以包含硬编码的数据记录块或脚本。为了本教程的目的，我们将坚持使用硬编码的数据记录块。如果您想学习 Datalog 脚本，请\*\*[访问此链接](https://www.learndatalogtoday.org/)\*\*。 我们将以下内容保存到文件中，名称为\*\*“authority.datalog”。\*\* user("admin"); 上面的块描述了持有此 Biscuit 代币的用户的角色。这些数据称为\*\*“事实\*\*”，稍后将根据服务器上的规则进行检查。事实可以是硬编码数据，也可以使用各种规则导出。 可以将以下类型的内容添加到 Biscuit 令牌中： 事实：像 user(\["admin", "moderator"\]) 这样的硬编码数据 规则：根据条件生成更多事实。稍后解释。 检查：添加检查以限制令牌。它们还用于稍后描述的衰减。 现在，我们将使用上述角色创建一个新的 Biscuit 令牌，并使用我们的私钥对其进行签名。要创建 Biscuit 授权令牌，请使用以下命令 > biscuit generate --private-key-file private-key authority.datalog // This is the generated Biscuit token EnYKDBgDIggKBggKEgIYDRIkCAASIHTT7y36m\_zlF2BqdHkkXbu8no8u8tXQI06\_BPmW2v17GkCnqmi4dKgkZX5b45542A5Ksuu\_ynBn7wpFNpFaCrAiF6wJpZAjbWXwuJ-dBEXHq8GnbvaHmTBjauT-af0NetcEIiIKIHU272x2JYg8rcnAt907nXXxQXqgG\_zoZFwA5v4Pgo6C _注意：我们使用了上面的_**_私钥_**_文件和_**_authority.datalog_**。 要检查 Biscuit 令牌的内容，请使用此命令。 > biscuit inspect - Please input a base64-encoded biscuit, followed by Enter and ^D // Input the biscuit key obtained from the step above EnYKDBgDIggKBggKEgIYDRIkCAASIHTT7y36m\_zlF2BqdHkkXbu8no8u8tXQI06\_BPmW2v17GkCnqmi4dKgkZX5b45542A5Ksuu\_ynBn7wpFNpFaCrAiF6wJpZAjbWXwuJ-dBEXHq8GnbvaHmTBjauT-af0NetcEIiIKIHU272x2JYg8rcnAt907nXXxQXqgG\_zoZFwA5v4Pgo6C Authority block: == Datalog == user("admin"); == Revocation id == 763fb15e229364e7ad3e10a73a9f3a1929def5dbb1e2628c243a488b2c3e926ac45e3c7dc7d6b6106ca19a427e48367b83ce4a35c17d9a404d9459a551f9fa03 ========== 🙈 Public key check skipped 🔑 🙈 Datalog check skipped 🛡️ 数据记录部分确认了我们的授权块。它还会生成一个撤销 ID，您可以根据需要使用该 ID 使令牌失效 **检查 Biscuit 代币权限** 要检查传入的 Biscuit 令牌（上面创建的）的权限（允许的权限），我们需要创建一组规则来检查给定的事实。如果传入的 Biscuit 代币符合规则，系统就允许用户使用该资源。简而言之，我们需要检查是否允许令牌执行请求的操作。 为此，我们需要创建另一个数据记录文件。我们将其称为**authorizer.datalog。** // Facts 1 user("admin"); time(2021-12-21T20:00:00Z); request("post"); // Facts2 resource("website"); backend("golang"); operation("create"); // Facts 3: server-side ACLs permission("admin", "website", "delete"); permission("admin", "website", "create"); permission("admin", "blog", "delete"); // Condition is\_allowed($user, $res, $op) user($user), resource($res), operation($op), permission($user, $res, $op); // allow/deny conditions allow if is\_allowed($user, $resource, $op); **_上述文件中有 3 个事实块：_** 事实1：从Biscuit代币获得的事实。假设 Biscuit 令牌是使用**Post**请求发送到授权者服务器应用程序的。然后，应用程序可以获得此信息、文件内容（**_User(“admin”)_**）、请求时间和请求类型（在我们的例子中为**_Post_**）。 事实 2：来自服务器应用程序的硬编码事实。当您需要基于特定服务器应用检查和条件时，这会派上用场。 事实 3：您可以从数据库等外部来源提取动态事实。在上面的示例中，列出了 ACL。 在事实之后，我们有一个**允许/拒绝条件**，它检查是否遵循所有规则以及用户是否获得授权。 让我们看看如何使用 CLI 授权用户...... > biscuit inspect - --verify-with-file authorizer.datalog --public-key 568e1a3876a327444f18414e66714d5deb908ba0b667ca9587bf9a03df8af478 Please input a base64-encoded biscuit, followed by Enter and ^D //Input the obtained biscuit token above EnYKDBgDIggKBggKEgIYDRIkCAASIHTT7y36m\_zlF2BqdHkkXbu8no8u8tXQI06\_BPmW2v17GkCnqmi4dKgkZX5b45542A5Ksuu\_ynBn7wpFNpFaCrAiF6wJpZAjbWXwuJ-dBEXHq8GnbvaHmTBjauT-af0NetcEIiIKIHU272x2JYg8rcnAt907nXXxQXqgG\_zoZFwA5v4Pgo6C Authority block: == Datalog == user("admin"); **_在authorizer.datalog_**文件中的规则和事实与规则进行检查后，系统通过授权规则，并授予用户权限。现在我们将学习如何削弱饼干代币。 **饼干代币衰减** 衰减是向用户授予低于层次结构中当前用户的某些权限的过程。权限始终小于当前用户的权限。衰减是通过向现有 Biscuit 附加新的权限（策略）块来实现的。此过程会生成一个新的 Biscuit，其权限比之前的 Biscuit 少。让我们看看如何做。 我们将制作一个新的衰减 Biscuit 代币，并使用新规则来检查用户是否是主持人\*\*。**创建一个新文件**pass-attenuated.datalog\*\*，并粘贴以下内容： check if operation($operation), $operation.matches("create"); **_请记住，为了制作减味饼干，我们需要向现有饼干文件添加新条件。_** 现在让我们使用上面的文件创建衰减的 Biscuit 授权令牌： > biscuit attenuate - --block-file 'pass-attenuated.datalog' Please input a base64-encoded biscuit, followed by Enter and ^D EnYKDBgDIggKBggKEgIYDRIkCAASIHTT7y36m\_zlF2BqdHkkXbu8no8u8tXQI06\_BPmW2v17GkCnqmi4dKgkZX5b45542A5Ksuu\_ynBn7wpFNpFaCrAiF6wJpZAjbWXwuJ-dBEXHq8GnbvaHmTBjauT-af0NetcEIiIKIHU272x2JYg8rcnAt907nXXxQXqgG\_zoZFwA5v4Pgo6C // Ouput - New attenuated biscuit token EnYKDBgDIggKBggKEgIYDRIkCAASIHTT7y36m\_zlF2BqdHkkXbu8no8u8tXQI06\_BPmW2v17GkCnqmi4dKgkZX5b45542A5Ksuu\_ynBn7wpFNpFaCrAiF6wJpZAjbWXwuJ-dBEXHq8GnbvaHmTBjauT-af0NetcEGpkBCi8KBmNyZWF0ZRgDMiMKIQoCCBsSBggDEgIIAxoTCgQKAggDCgUKAxiACAoEGgIIBRIkCAASINK\_87K2NdXFaQVCA2Dq-\_fh-DE6i9Y9NJmlxOVB2kSZGkDOCWoLe4GR\_TBrx4Y8S\_WEM4Q77NWCyFtKeDW78lInHMWfkQ7zWfYwDzcJGdVoYw\_52wxv67SI660cEZ8ETrUOIiIKIJGKPgwGyDwJkJS61HTrfxlcLV83BjTO5tav64Xv5UEw 现在你有了一个新的减毒饼干代币。让我们使用之前运行的命令验证新令牌并查看其内容： > biscuit inspect - Please input a base64-encoded biscuit, followed by Enter and ^D // Input the new attenuated biscuit token EnYKDBgDIggKBggKEgIYDRIkCAASIHTT7y36m\_zlF2BqdHkkXbu8no8u8tXQI06\_BPmW2v17GkCnqmi4dKgkZX5b45542A5Ksuu\_ynBn7wpFNpFaCrAiF6wJpZAjbWXwuJ-dBEXHq8GnbvaHmTBjauT-af0NetcEGpkBCi8KBmNyZWF0ZRgDMiMKIQoCCBsSBggDEgIIAxoTCgQKAggDCgUKAxiACAoEGgIIBRIkCAASINK\_87K2NdXFaQVCA2Dq-\_fh-DE6i9Y9NJmlxOVB2kSZGkDOCWoLe4GR\_TBrx4Y8S\_WEM4Q77NWCyFtKeDW78lInHMWfkQ7zWfYwDzcJGdVoYw\_52wxv67SI660cEZ8ETrUOIiIKIJGKPgwGyDwJkJS61HTrfxlcLV83BjTO5tav64Xv5UEw Authority block: == Datalog == user("admin"); == Revocation id == a7aa68b874a824657e5be39e78d80e4ab2ebbfca7067ef0a4536915a0ab02217ac09a590236d65f0b89f9d0445c7abc1a76ef6879930636ae4fe69fd0d7ad704 ========== Block n°1: == Datalog == check if operation($operation), $operation.contains("create"); == Revocation id == ce096a0b7b8191fd306bc7863c4bf58433843becd582c85b4a7835bbf252271cc59f910ef359f6300f370919d568630ff9db0c6febb488ebad1c119f044eb50e ========== 🙈 Public key check skipped 🔑 🙈 Datalog check skipped 🛡️ 如果仔细观察输出，您会注意到令牌中的一个新块确认了衰减令牌： Block n°1: == Datalog == check if operation($operation), $operation.contains("create"); **检查减弱的 Biscuit 令牌** 最后让我们检查一下新的衰减 Biscuit 令牌是否在服务器上得到验证。我们可以运行我们已经知道的命令： > biscuit inspect - --verify-with-file authorizer.datalog --public-key 568e1a3876a327444f18414e66714d5deb908ba0b667ca9587bf9a03df8af478 Please input a base64-encoded biscuit, followed by Enter and ^D // Enter the new biscuit attenuated token EnYKDBgDIggKBggKEgIYDRIkCAASIHTT7y36m\_zlF2BqdHkkXbu8no8u8tXQI06\_BPmW2v17GkCnqmi4dKgkZX5b45542A5Ksuu\_ynBn7wpFNpFaCrAiF6wJpZAjbWXwuJ-dBEXHq8GnbvaHmTBjauT-af0NetcEGpkBCi8KBmNyZWF0ZRgDMiMKIQoCCBsSBggDEgIIAxoTCgQKAggDCgUKAxiACAoEGgIIBRIkCAASINK\_87K2NdXFaQVCA2Dq-\_fh-DE6i9Y9NJmlxOVB2kSZGkDOCWoLe4GR\_TBrx4Y8S\_WEM4Q77NWCyFtKeDW78lInHMWfkQ7zWfYwDzcJGdVoYw\_52wxv67SI660cEZ8ETrUOIiIKIJGKPgwGyDwJkJS61HTrfxlcLV83BjTO5tav64Xv5UEw Authority block: == Datalog == user("admin"); == Revocation id == a7aa68b874a824657e5be39e78d80e4ab2ebbfca7067ef0a4536915a0ab02217ac09a590236d65f0b89f9d0445c7abc1a76ef6879930636ae4fe69fd0d7ad704 ========== Block n°1: == Datalog == check if operation($operation), $operation.contains("create"); == Revocation id == ce096a0b7b8191fd306bc7863c4bf58433843becd582c85b4a7835bbf252271cc59f910ef359f6300f370919d568630ff9db0c6febb488ebad1c119f044eb50e ========== ✅ Public key check succeeded 🔑 ✅ Authorizer check succeeded 🛡️ Matched allow policy: allow if is\_allowed($user, $resource, $op) **_结果：通过_** 如您所见，服务器成功验证了衰减令牌。**在pass-attenuated.datalog**文件上使用不同的参数运行一些测试，并检查授权者允许哪些参数。 **测试** 尝试使用以下详细信息创建一个新的减毒饼干，看看它是否通过。 check if user($user), $user.contains("moderator"); \*\*你的测试应该会失败，或者你的规则或事实有问题。\*\*‍ **结论** Biscuit 授权令牌对于微服务架构来说是令人惊叹的授权令牌。它可以帮助您在实施授权时节省大量时间，同时还提供一流的安全性。在本教程中，我们学习了 Biscuit 的基础知识并了解了如何使用 Biscuit CLI。 **奇拉莱·穆沙哈里** 软件工程师 Chilarai 在 Space and Time 担任软件工程师承包商。他拥有十多年开发产品和围绕产品创建生态系统的经验。他之前曾与网络安全和分析公司合作构建工具来处理桌面和云服务器上的大量数据。Chilarai 也是一位热心的开源倡导者和贡献者。

---

*Originally published on [ma1984.eth](https://paragraph.com/@ma1984/OMhmbqL4j6gRotRg2UM2)*
