

# 步骤 3：分发参与者令牌
<a name="getting-started-distribute-tokens"></a>

现在您拥有了暂存区，您需要创建令牌并将其分发给参与者，以使参与者能够加入暂存区并开始发送和接收视频。有两种生成令牌的方法：
+ 使用密钥对[创建](#getting-started-distribute-tokens-self-signed)令牌。
+ [使用 IVS 实时直播 API 创建令牌](#getting-started-distribute-tokens-api)。

下面介绍了这两种方法。

## 使用密钥对创建令牌
<a name="getting-started-distribute-tokens-self-signed"></a>

您可以在服务器应用程序上创建令牌并将其分发给参与者以加入暂存区。您需要生成一个 ECDSA 公有/私有密钥对以对 JWT 进行签名，并将公有密钥导入到 Amazon IVS。然后，IVS 可以在暂存区加入时验证令牌。

IVS 不提供密钥到期功能。如果您的私有密钥遭到泄露，则必须删除旧的公有密钥。

### 创建新密钥对
<a name="getting-started-distribute-tokens-self-signed-create-key-pair"></a>

可通过各种方法创建密钥对。下面，我们举两个例子。

要在控制台中创建新的密钥对，请按照以下步骤操作：

1. 打开 [Amazon IVS 控制台](https://console.aws.amazon.com/ivs)。如果您尚未选择暂存区所在的区域，请选择区域。

1. 在左侧导航菜单中，选择**实时直播功能 > 公有密钥**。

1. 选择**创建公有密钥**。系统会显示**创建公有密钥**对话框。

1. 按照提示操作并选择 **Create (创建)**。

1. Amazon IVS 将生成新的密钥对。公有密钥将作为公有密钥资源导入，私有密钥立即可供下载。如有必要，也可以稍后下载公有密钥。

   Amazon IVS 在客户端生成密钥，并且不存储私有密钥。***请务必保存好密钥；您之后无法检索此密钥。***

要使用 OpenSSL 创建新的 P384 EC 密钥对（您可能需要先安装 [OpenSSL](https://www.openssl.org/source/)），请按照以下步骤操作。此过程允许您访问私有密钥和公有密钥。只有当您想测试令牌的验证时，才需要公有密钥。

```
openssl ecparam -name secp384r1 -genkey -noout -out priv.pem
openssl ec -in priv.pem -pubout -out public.pem
```

现在按照以下说明导入新的公有密钥。

### 导入公有密钥
<a name="getting-started-distribute-tokens-import-public-key"></a>

拥有密钥对后，您可以将公有密钥导入 IVS。我们的系统不需要私有密钥，但您可以使用私有密钥来签署令牌。

要使用控制台导入现有公有密钥，请执行以下操作：

1. 打开 [Amazon IVS 控制台](https://console.aws.amazon.com/ivs)。如果您尚未选择暂存区所在的区域，请选择区域。

1. 在左侧导航菜单中，选择**实时直播功能 > 公有密钥**。

1. 选择**导入**。系统会显示**导入公有密钥**对话框。

1. 按照提示操作并选择 **Import (导入)**。

1. Amazon IVS 会导入您的公有密钥并生成公有密钥资源。

要使用 CLI 导入现有公有密钥，请执行以下操作：

```
aws ivs-realtime import-public-key --public-key-material "`cat public.pem`" --region <aws-region>
```

如果区域位于您的本地亚马逊云科技配置文件中，您可以忽略 `--region <aws-region>`。

以下是响应示例：

```
{
    "publicKey": {
        "arn": "arn:aws:ivs:us-west-2:123456789012:public-key/f99cde61-c2b0-4df3-8941-ca7d38acca1a",
        "fingerprint": "98:0d:1a:a0:19:96:1e:ea:0a:0a:2c:9a:42:19:2b:e7",
        "publicKeyMaterial": "-----BEGIN PUBLIC KEY-----\nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEVjYMV+P4ML6xemanCrtse/FDwsNnpYmS\nS6vRV9Wx37mjwi02hObKuCJqpj7x0lpz0bHm5v1JBvdZYAd/r2LR5aChK+/GM2Wj\nl8MG9NJIVFaw1u3bvjEjzTASSfS1BDX1\n-----END PUBLIC KEY-----\n",
        "tags": {}
    }
}
```

### API 请求
<a name="getting-started-distribute-tokens-create-api"></a>

```
POST /ImportPublicKey HTTP/1.1
{
  "publicKeyMaterial": "<pem file contents>"
}
```

### 生成并签名令牌
<a name="getting-started-distribute-tokens-self-signed-generate-sign"></a>

有关使用 JWT 和受支持的库签名令牌的详细信息，请访问 [jwt.io](https://jwt.io/)。在 jwt.io 界面上，您必须输入私有密钥才能签署令牌。只有当您想验证令牌时才需要公有密钥。

所有 JWT 都有三个字段：标头、有效负载和签名。

JWT 标头和有效载荷的 JSON 架构如下所述。或者，您可以从 IVS 控制台复制示例 JSON。从 IVS 控制台获取标头和有效载荷 JSON：

1. 打开 [Amazon IVS 控制台](https://console.aws.amazon.com/ivs)。如果您尚未选择暂存区所在的区域，请选择区域。

1. 在左侧导航窗格中，选择**实时直播功能 > 暂存区**。

1. 选择要使用的暂存区。选择 **View details (查看详细信息)**。

1. 在**参与者令牌**部分，选择**创建令牌**旁边的下拉菜单。

1. 选择**生成令牌标题和有效载荷**。

1. 填写表单并复制弹出窗口底部显示的 JWT 标题和有效载荷。

#### 令牌架构：标头
<a name="getting-started-distribute-tokens-self-signed-generate-sign-header"></a>

标头指定了如下内容：
+ `alg` 是签名算法。这是 ES384，是一种使用 SHA-384 哈希算法的 ECDSA 签名算法。
+ `typ` 是令牌类型（即 JWT）。
+ `kid` 是用于对令牌进行签名的公有密钥的 ARN。它必须与从 [GetPublicKey](https://docs.aws.amazon.com//ivs/latest/RealTimeAPIReference/API_GetPublicKey.html) API 请求返回的 ARN 相同。

```
{
  "alg": "ES384",
  "typ": "JWT"
  “kid”: “arn:aws:ivs:123456789012:us-east-1:public-key/abcdefg12345”
}
```

#### 令牌架构：有效载荷
<a name="getting-started-distribute-tokens-self-signed-generate-sign-payload"></a>

有效载荷包含特定于 IVS 的数据。除 `user_id` 之外的所有字段均为必填字段。
+ JWT 规范中的 `RegisteredClaims` 是保留声明，需要提供这些声明才能使暂存区令牌生效：
  + `exp`（过期时间）是令牌过期时的 Unix UTC 时间戳。（Unix 时间戳是一个数值，表示从 1970-01-01T00:00:00Z UTC 到指定 UTC 日期/时间的秒数，忽略闰秒。） 当参与者加入暂存区时，会对令牌进行验证。IVS 提供的令牌默认有 12 小时的 TTL，建议使用该值；从签发时间（iat）起，最多可延长至 14 天。此项必须是整型值。
  + `iat`（签发时间）是 JWT 签发时的 Unix UTC 时间戳。（有关 Unix 时间戳的信息，请参阅 `exp` 的说明。） 该项必须是整型值。
  + `jti`（JWT ID）是用于跟踪和引用授予令牌的参与者的参与者 ID。每个令牌必须具有唯一的参与者 ID。它必须是区分大小写的字符串，长度最多 64 个字符，仅包含字母数字字符、连字符（-）和下划线（\$1）字符。不允许使用其他特殊字符。
+ `user_id` 是客户分配的可选名称，用于帮助识别令牌；此项可用于将参与者链接到客户自己系统中的用户。此项应该与 [CreateParticipantToken](https://docs.aws.amazon.com/ivs/latest/RealTimeAPIReference/API_CreateParticipantToken.html) API 请求中的 `userId` 字段相匹配。它可以是任何 UTF-8 编码的文本，并且是最多 128 个字符的字符串。*此字段向所有暂存区参与者公开，不应用于个人身份识别、机密或敏感信息。*
+ `resource` 是暂存区的 ARN；例如，`arn:aws:ivs:us-east-1:123456789012:stage/oRmLNwuCeMlQ`。
+ `topic` 是暂存区的 ID，可以从暂存区 ARN 中提取。例如，如果暂存区 ARN 为 `arn:aws:ivs:us-east-1:123456789012:stage/oRmLNwuCeMlQ`，则暂存区 ID 为 `oRmLNwuCeMlQ`。
+ `events_url` 必须是从 CreateStage 或 GetStage 操作返回的事件端点。建议您在创建暂存区时缓存此值；该值最多可以缓存 14 天。示例值为 `wss://global.events.live-video.net`。
+ `whip_url` 必须是从 CreateStage 或 GetStage 操作返回的 WHIP 端点。建议您在创建暂存区时缓存此值；该值最多可以缓存 14 天。示例值为 `https://453fdfd2ad24df.global-bm.whip.live-video.net`。
+ `capabilities` 指定令牌的功能；有效值为 `allow_publish` 和 `allow_subscribe`。对于仅订阅令牌，仅将 `allow_subscribe` 设置为 `true`。
+ `attributes` 是一个可选字段，您可以在其中指定应用程序提供的属性以编码到令牌中并附加到暂存区。映射键和值可以包含 UTF-8 编码的文本。此字段的最大长度总共为 1 KB。*此字段向所有暂存区参与者公开，不应用于个人身份识别、机密或敏感信息。*
+ `version` 必须是 `1.0`。

  ```
  {
    "exp": 1697322063,
    "iat": 1697149263,
    "jti": "Mx6clRRHODPy",
    "user_id": "<optional_customer_assigned_name>",
    "resource": "<stage_arn>",
    "topic": "<stage_id>",
    "events_url": "wss://global.events.live-video.net",
    "whip_url": "https://114ddfabadaf.global-bm.whip.live-video.net",
    "capabilities": {
      "allow_publish": true,
      "allow_subscribe": true
    },
    "attributes": {
      "optional_field_1": "abcd1234",
      "optional_field_2": "false"
    },
    "version": "1.0"
  }
  ```

#### 令牌架构：签名
<a name="getting-started-distribute-tokens-self-signed-generate-sign-signature"></a>

要创建签名，可搭配使用私有密钥和标头 (ES384) 中指定的算法，对已编码的标头和已编码的负载进行签名。

```
ECDSASHA384(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  <private-key>
)
```

#### 说明
<a name="getting-started-distribute-tokens-self-signed-generate-sign-instructions"></a>

1. 使用 ES384 签名算法以及与提供给 IVS 的公有密钥关联的私有密钥生成令牌签名。

1. 汇编令牌。

   ```
   base64UrlEncode(header) + "." +
   base64UrlEncode(payload) + "." +
   base64UrlEncode(signature)
   ```

## 使用 IVS 实时直播功能 API 创建令牌
<a name="getting-started-distribute-tokens-api"></a>

![\[分发参与者令牌：舞台令牌工作流程\]](http://docs.aws.amazon.com/zh_cn/ivs/latest/RealTimeUserGuide/images/Distribute_Participant_Tokens.png)


如上所示，客户端应用程序要求服务器应用程序提供令牌，服务器应用程序使用 AWS SDK 或 SigV4 签名请求调用 CreateParticipantToken。由于 AWS 凭证用于调用 API，因此应在安全的服务器端应用程序中生成令牌，而不是在客户端应用程序中。

创建参与者令牌时，您可以选择指定属性和/或功能：
+ 您可以指定应用程序提供的属性以编码到令牌中并附加到暂存区。映射键和值可以包含 UTF-8 编码的文本。此字段的最大长度总共为 1 KB。*此字段向所有暂存区参与者公开，不应用于个人身份识别、机密或敏感信息。*
+ 您可以指定令牌启用的功能。默认功能为 `PUBLISH` 和 `SUBSCRIBE`，该功能允许参与者发送和接收音频和视频，但您可以发布具有子集功能的令牌。例如，您可以为监管人发布仅具有 `SUBSCRIBE` 功能的令牌。在这种情况下，监管人可以看到正在发送视频但不发送自己视频的参与者。

有关详细信息，请参阅 [CreateParticipantToken](https://docs.aws.amazon.com//ivs/latest/RealTimeAPIReference/API_CreateParticipantToken.html)。

您可以通过控制台或 CLI 创建参与者令牌以进行测试和开发，但您很可能希望在生产环境中使用 AWS SDK 创建令牌。

您需要一种将令牌从服务器分发到每个客户端（例如，通过 API 请求）的方法。我们不提供此功能。在本指南中，您只需遵循以下步骤，即可将令牌复制并粘贴到客户端代码。

**重要**：将令牌视为不透明；也就是说，不要根据令牌内容构建功能。令牌的格式未来可能会发生变化。

### 控制台说明
<a name="getting-started-distribute-tokens-console"></a>

1. 导航到您在上一步骤中创建的舞台。

1. 选择**创建令牌**。将出现**创建令牌**窗口。

1. 输入要与令牌关联的用户 ID。这可以是任何 UTF-8 编码的文本。

1. 选择**创建**。

1. 复制令牌。*重要提示：请务必保存令牌；IVS 不存储令牌，您之后也无法检索令牌*。

### CLI 说明
<a name="getting-started-distribute-tokens-cli"></a>

使用 AWS CLI 创建令牌需要您先在计算机上下载并配置 CLI。有关详细信息，请参阅 [Amazon 命令行界面用户指南](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html)。注意：使用 AWS CLI 生成令牌适合用于测试目的，但对于生产用途而言，我们建议您使用 AWS SDK 在服务器端生成令牌（请参阅以下说明）。

1. 使用舞台 ARN 运行 `create-participant-token` 命令。包括以下任何或所有功能：`"PUBLISH"`、`"SUBSCRIBE"`。

   ```
   aws ivs-realtime create-participant-token --stage-arn arn:aws:ivs:us-west-2:376666121854:stage/VSWjvX5XOkU3 --capabilities '["PUBLISH", "SUBSCRIBE"]'
   ```

1. 这将返回一个参与者令牌：

   ```
   {
       "participantToken": {
           "capabilities": [
               "PUBLISH",
               "SUBSCRIBE"
           ],
           "expirationTime": "2023-06-03T07:04:31+00:00",
           "participantId": "tU06DT5jCJeb",
           "token": "eyJhbGciOiJLTVMiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2NjE1NDE0MjAsImp0aSI6ImpGcFdtdmVFTm9sUyIsInJlc291cmNlIjoiYXJuOmF3czppdnM6dXMtd2VzdC0yOjM3NjY2NjEyMTg1NDpzdGFnZS9NbzhPUWJ0RGpSIiwiZXZlbnRzX3VybCI6IndzczovL3VzLXdlc3QtMi5ldmVudHMubGl2ZS12aWRlby5uZXQiLCJ3aGlwX3VybCI6Imh0dHBzOi8vNjZmNzY1YWM4Mzc3Lmdsb2JhbC53aGlwLmxpdmUtdmlkZW8ubmV0IiwiY2FwYWJpbGl0aWVzIjp7ImFsbG93X3B1Ymxpc2giOnRydWUsImFsbG93X3N1YnNjcmliZSI6dHJ1ZX19.MGQCMGm9affqE3B2MAb_DSpEm0XEv25hfNNhYn5Um4U37FTpmdc3QzQKTKGF90swHqVrDgIwcHHHIDY3c9eanHyQmcKskR1hobD0Q9QK_GQETMQS54S-TaKjllW9Qac6c5xBrdAk"
       }
   }
   ```

1. 保存该令牌。您需要此令牌才能加入舞台并发送和接收视频。

### AWS SDK 说明
<a name="getting-started-distribute-tokens-sdk"></a>

您可以使用 AWS SDK 创建令牌。以下是使用 JavaScript 的 AWS SDK 的说明。

**重要提示：**此代码必须在服务器端执行，并将其输出内容传递给客户端。

**先决条件：**要使用下面的代码示例，您需要安装 aws-sdk/client-ivs-realtime 程序包。有关详细信息，请参阅 [Getting started with the AWS SDK for JavaScript](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/getting-started.html)。

```
import { IVSRealTimeClient, CreateParticipantTokenCommand } from "@aws-sdk/client-ivs-realtime";

const ivsRealtimeClient = new IVSRealTimeClient({ region: 'us-west-2' });
const stageArn = 'arn:aws:ivs:us-west-2:123456789012:stage/L210UYabcdef';
const createStageTokenRequest = new CreateParticipantTokenCommand({
  stageArn,
});
const response = await ivsRealtimeClient.send(createStageTokenRequest);
console.log('token', response.participantToken.token);
```