# 将 Vivox 访问令牌与 UAS 结合使用

> Follow this workflow to use Vivox Access Tokens together with Unity Authentication Services.

为了完全控制哪些玩家可以访问哪些频道，您可以通过自己的后端生成 Vivox 访问令牌 (VAT)。

> **Tip:**
>
> \*\*提示：\*\*此流程对于已有 VAT 流程的项目特别有用，这种情况下可以利用完整的 Vivox Safety 套件或其他 Unity 服务。

> **Important:**
>
> \*\*重要：\*\*仅当需要其他无法使用常规 UAS 令牌实现的频道访问控制功能时，或者您已经是 VAT 用户并想要与 UAS 集成时，才使用此流程。

**先决条件**：

1. [设置 Unity Cloud 项目](/services/getting-started.md)
   * 确保您拥有 Project ID、环境 ID 和环境名称。
2. [启用 UAS 自定义 ID 提供商](/authentication/platform-signin/custom-id.md)
   * 确保您在此设置中拥有服务帐户凭据。

此设置的总体流程如下图所示：

![](/api/media?file=/vivox-unity/media/images/vat-creation-flow-using-uas-tokens.png)

## 创建 VAT##creating-vats

1. 每当需要 VAT 时，Vivox SDK 都会使用自定义令牌提供商实现从后端请求 VAT。
2. 在 `GetTokenAsync` 方法内请求 VAT 时，向后端的请求中添加 `accessToken`。
3. 在后端从令牌中验证并提取所需的信息，并创建 Vivox 访问令牌以将其发送回客户端。

## 客户端设置##vat-creation-flow

在游戏客户端中，创建一个实现 Vivox SDK `IVivoxTokenProvider` 接口的类并将其注册到 VivoxService。

如果通过调用 `VivoxService.Instance.SetTokenProvider` 来注册 IVivoxTokenProvider 的实现，则每当需要令牌进行登录等操作时，Vivox 都会调用您的实现中的 `IVivoxTokenProvider.GetTokenAsync` 方法。

创建有效负载所需的信息作为覆盖的 `IVivoxTokenProvider.GetTokenAsync` 方法的输入提供。此信息在制作 VAT 时使用。

您仍然必须设置服务器端令牌供应，并在覆盖的 `IVivoxTokenProvider.GetTokenAsync` 方法中获取令牌。

### 订阅##to-subscribe

在登录您的玩家之前，您必须使用以下方法注册您的 `IVivoxTokenProvider` 实现：

```text
VivoxService.Instance.SetTokenProvider(new CustomTokenProvider());
```

> **Important:**
>
> \*\*重要：\*\*订阅流程在 v16.5.0 中发生了变化。对于 16.5.0 之前的 Unity Vivox SDK 版本，您必须在初始化 Vivox SDK 之前注册您的 `IVivoxTokenProvider` 实现。

### 获取令牌##fetch-the-token

应使用覆盖的方法中提供的所有参数（即使有些参数为空）创建有效负载，并将有效负载发送到您的安全服务器以生成您的 Vivox 访问令牌。

最佳做法是发送所有参数；仅返回有效负载所需的内容。使用有效负载作为 `GetTokenAsync` 方法中的输入。

此外，您必须在请求的有效负载中发送 UAS accessToken，以便服务器对其进行验证并根据它生成 Vivox 访问令牌。

对于某些令牌，不同的参数将为空。例如，登录令牌的 `targetUserUri` 和 `channelUri` 将为空。这是预期的行为。

以下是一个令牌生成示例。

```cs
public class VoiceManager : MonoBehaviour
{
    async void Start()
    {
        // Must be done before any other Vivox action otherwise tokens will not be generated properly.
        VivoxService.Instance.SetTokenProvider(new VivoxTokenProvider());
        await UnityServices.InitializeAsync();
        await VivoxService.Instance.InitializeAsync();
    }
}

class VivoxTokenProvider : IVivoxTokenProvider
{
    public Task<string> GetTokenAsync(string issuer = null, TimeSpan? expiration = null, string targetUserUri = null, string action = null, string channelUri = null, string fromUserUri = null, string realm = null)
    {
        if (!AuthenticationService.Instance.SessionTokenExists)
        {
          // Player not logged in!
        }
        var accessToken = AuthenticationService.Instance.AccessToken
        // Implement token fetching logic here.
        // The method parameters together with the accessToken from the AuthenticationService contain the necessary information for crafting the request payload.
        // This will be called whenever a token is needed for a Vivox action
    }
}
```

## 服务器端设置##client-side-setup

您的后端服务需要公开一个 API，让客户端可以在[以上](#fetch-the-token)的 `GetTokenAsync` 函数中调用该 API，以便在需要时接收 VAT。

请参阅[在安全服务器上生成令牌](../../access-token-guide/generate-token-secure-server/generate-token-secure-server-toc)以详细了解关于如何创建 VAT 的实现细节。

请参阅[访问令牌有效负载](../../access-token-guide/access-token-format/access-token-payload)以了解有关令牌有效负载的更多信息。

创建 VAT 时，您需要使用以下用户 SIP URI 作为主体：

```text
sip:.issuer.unity_player_id.unity_environment_id.@domain.vivox.com
```

`issuer` 表示 Unity 项目的 Vivox 令牌颁发者。`unity_player_id` 表示 UAS 玩家 ID。`unity_environment_id` 表示 Unity Cloud 环境的环境 ID。

这两个值都可以从应该在 `GetTokenAsync` 方法内从客户端发送到后端的 accessToken 中提取。

然后应按照[验证令牌 ID](https://services.docs.unity.com/docs/client-auth/#validate-the-token-id) 中描述的步骤验证 `accessToken`。

令牌的 `sub` 声明中包含 UAS 玩家 ID。令牌的 `aud` 声明中包含环境 ID。`aud` 值是一个区分大小写的字符串数组，每个字符串包含一个 StringOrURI 值。

```json
{
  "header": {
    "alg": "RS256",
    "kid": "<id>",
    "typ": "JWT"
  },
  "payload": {
    "aud": [
      "upid:{{unity_project_id}}",
      "envName:{{environment_name}}",
      "envId:{{unity_environment_id}}" // unity environment id
    ],
    "exp": 1617677595, // expires at
    "iat": 1617673872, // issued at
    "nbf": 1617673872, // not valid before
    "sub": "{{unity_player_id}}", // UAS player ID
    "project_id": "{{unity_project_id}}" // unity project id
  }
}
```

这样就可以创建 VAT 并将其返回到客户端。
