> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# PlayFab Party 邀请和安全模型

> 关于 PlayFab Party 邀请如何授权玩家加入网络,以及安全模型如何控制聊天和数据访问的概念性概述。

PlayFab Party 旨在默认提供安全的通信环境。这有助于保护游戏和玩家,但安全限制可能会引起开发者对 API 使用的疑问。本页介绍 PlayFab Party 的安全功能,主要关注邀请和使用它们的有效模式。

PlayFab Party 对所有通信(管理数据、游戏数据和实时通信)使用行业标准的加密和身份验证。这包括所有点对点传输以及所有到 Azure 服务的事务,无论是 Web 服务(使用 HTTPS)还是透明云中继服务(使用 DTLS)。

限制对网络的访问是保护网络完整性的核心部分。加入网络需要四件事:

* 了解[网络描述符](/services/playfab/multiplayer/networking/concepts-objects#network)
* 拥有有效的 PlayFab `title_player_account` [实体令牌](/services/playfab/live-service-management/game-configuration/entities)
* 了解邀请[标识符](#identifiers)
* 该令牌的 PlayFab [实体 ID](/services/playfab/live-service-management/game-configuration/entities) 存在于指定的邀请中,或指定的邀请是[开放邀请](#users-and-open-invitations)

给定的 PlayFab Party 网络最多可以有 [128 名玩家](https://learn.microsoft.com/en-us/rest/api/playfab/multiplayer/multiplayer-server/request-party-service#partynetworkconfiguration)。

## 邀请

邀请(`PartyInvitation`)是网络内的一个对象,授予用户访问网络的权限。可以在网络的整个生命周期内[创建](#creation)和[撤销](#revocation)邀请。邀请具有[创建者](#creation)、唯一[标识符](#identifiers)、[可撤销性设置](#initial-invitation-and-other-invitations)以及可选的以实体 ID 指定的[用户集](#users-and-open-invitations)。网络可以拥有任意数量的活跃邀请,包括零个。网络始终随初始邀请一起创建。

## 邀请生命周期

邀请从创建时起处于活跃状态,直到被撤销。

### 创建

有两种方式可以创建邀请。第一种方式是调用 `PartyManager::CreateNewNetwork()`。由于加入网络需要邀请,因此在创建网络时必须存在一个邀请。此邀请称为初始邀请,具有[下面描述的](#initial-invitation-and-other-invitations)一些特殊属性。第二种方式是调用 `PartyNetwork::CreateInvitation()`。

邀请的创建者是调用 `PartyNetwork::CreateInvitation()` 时指定的用户。初始邀请没有创建者。

创建邀请时(或使用活跃的初始邀请加入网络时),会生成一个 `PartyInvitationCreatedStateChange`。

<Info>
  初始邀请并不隐式地允许网络创建者加入。除非使用[开放邀请](#users-and-open-invitations),否则请务必将创建者的实体 ID 包含在用户列表中。
</Info>

### 枚举

使用 `PartyNetwork::GetInvitations()` 枚举活跃邀请。只有在本地设备上创建的邀请以及初始邀请(如果仍然活跃)可以被枚举。

### 撤销

通过调用 `PartyNetwork::RevokeInvitation()` 撤销邀请。除初始邀请外,只有邀请的创建者才能撤销该邀请,而初始邀请可以由任何用户撤销。此外,当创建邀请的用户从网络中移除时,该邀请将被自动撤销。

撤销邀请时,所有能够看到该邀请的设备上都会生成一个 `PartyInvitationRevokedStateChange`。

一旦初始邀请被撤销,就无法再次创建。其标识符可以被重复用于新邀请,但该新邀请不具备初始邀请的特殊属性。

<Info>
  撤销邀请对已经加入网络的设备和用户没有影响。要从网络中移除用户或设备,请使用 `PartyNetwork::KickUser()` 或 `PartyNetwork::KickDevice()`。请注意,这些方法尚未实现。
</Info>

## 邀请配置

邀请的配置在创建期间使用 `PartyInvitationConfiguration` 结构指定。

### 标识符

每个邀请都有一个在网络内唯一标识它的标识符。如果在创建邀请时未指定标识符,Party 会分配一个。对于调用 `PartyManager::CreateNewNetwork()`,分配的标识符通过输出参数返回,并且在网络创建完成时也在 `PartyCreateNewNetworkCompletedStateChange` 中报告。对于调用 `PartyManager::CreateInvitation()`,可以在邀请创建完成时从 `invitation` 输出参数或 `PartyCreateInvitationCompletedStateChange` 中的 `invitation` 字段检索分配的标识符。

尽管邀请标识符必须是唯一的,但在邀请被撤销后,其标识符可以在创建新邀请时被重复使用。

### 初始邀请和其他邀请

尽管只有一种邀请类型,但调用 `PartyManager::CreateNewNetwork()` 创建的初始邀请与稍后通过 `PartyNetwork::CreateInvitation()` 创建的邀请略有不同。差异总结如下表所示。

| 属性   | 初始邀请                                                                                                                                         | 其他邀请                                                                                                                         |
| ---- | -------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| 可见性  | 所有设备都可以看到初始邀请。只要初始邀请未被撤销,对 `PartyNetwork::GetInvitations()` 的调用都会返回初始邀请。加入网络时,如果初始邀请此前未被撤销,每个设备都会为其收到一个 `PartyInvitationCreatedStateChange`。 | 只有创建邀请的设备才能看到该邀请。只有在该设备上创建的非初始邀请才会由 `PartyNetwork::GetInvitations()` 返回,并且仅在创建者的设备上为其生成 `PartyInvitationCreatedStateChange`。 |
| 可撤销性 | 任何人都可以撤销初始邀请。显式指定邀请配置时,可撤销性必须设置为 `PartyInvitationRevocability::Anyone`。                                                                      | 只有创建者可以撤销邀请。创建邀请时,可撤销性必须设置为 `PartyInvitationRevocability::Creator`。                                                          |
| 生命周期 | 初始邀请一直处于活跃状态,直到被显式撤销。                                                                                                                        | 非初始邀请一直处于活跃状态,直到被显式撤销,或直到创建它的用户从网络中移除。当用户从网络中移除时,他们创建的所有邀请都将自动被撤销。                                                           |
| 创建者  | 初始邀请没有创建者。`PartyInvitation::GetCreatorEntityId()` 返回 null。                                                                                   | 调用 `PartyNetwork::CreateInvitation` 时指定的用户是创建者。`PartyInvitation::GetCreatorEntityId()` 返回该用户的实体 ID。                          |

出于隐私原因,邀请(初始邀请除外)对其他设备是隐藏的。有关这为什么重要的示例,请参阅[好友列表使用模式](#friends-list)。

### 用户和开放邀请

邀请包含 0 或更多以 `title_player_account` [实体 ID](/services/playfab/live-service-management/game-configuration/entities) 指定的用户。如果邀请包含用户,则该邀请仅授予这些用户加入网络的访问权限。然而,如果邀请不包含用户,则它是开放邀请。任何用户都可以使用开放邀请的标识符加入网络。

<Note>
  在多用户设备(例如游戏主机)上,请务必将正确的邀请与正确的用户配合使用。取决于每个邀请中指定的用户,设备上的不同用户可能需要在通过 PartyNetwork::AuthenticateLocalUser() 将用户身份验证到网络时使用不同的邀请。
</Note>

### 不可变性

一旦创建邀请,其配置就无法更改。但是,在邀请被撤销后,可以创建具有相同标识符但不同配置的另一个邀请。请参阅[动态单一邀请使用模式](#dynamic-single-invitation)。

## 使用模式

PlayFab Party 邀请简单但灵活。有许多有效的方式可以使用它们来为网络实现不同的访问模型。

### 开放网络

开放网络最容易理解和实现。它允许任何拥有网络描述符和邀请标识符的人加入。

在调用 `PartyManager::CreateNewNetwork()` 时,将 `initialInvitationConfiguration` 参数传递为 null 以创建开放网络。开放邀请的标识符作为输出参数返回。网络创建完成后,共享网络描述符和邀请标识符以允许用户加入。

你可以选择在将来的任何时候通过撤销初始邀请来关闭网络。

<Warning>
  由于网络的安全性取决于加入它的设备和用户,因此在共享开放网络的网络描述符和邀请标识符时请谨慎行事。
</Warning>

### 静态用户列表

对于事先知道所有玩家的游戏,例如没有回填的匹配创建的对局,静态用户列表是一种简单有效的模式。它只允许在游戏开始前确定的用户加入网络。

创建 `PartyInvitationConfiguration` 结构并将已知用户添加到其 `entityIds` 字段。将此结构传入 `PartyManager::CreateNewNetwork()`。网络创建完成后,共享网络描述符和邀请标识符以允许用户加入。

### 一对一邀请

在现有用户单独邀请其他用户的游戏中,一对一邀请模式简单有效。

创建 `PartyInvitationConfiguration` 结构,只将创建者添加到其 `entityIds` 字段。将此结构传入 `PartyManager::CreateNewNetwork()`。创建者连接到网络后,可以选择撤销初始邀请。或者,网络的创建者可以创建一个[开放网络](#open-network),然后在连接后立即撤销初始邀请。

为应加入网络的每位用户创建另一个 `PartyInvitationConfiguration` 结构。通过将这些结构传入 `PartyNetwork::CreateInvitation()` 创建邀请。将网络描述符与每位用户及其特定邀请的邀请标识符一起共享。用户加入时,他们可以重复此模式以邀请更多用户。

用户加入后,可以选择撤销其特定邀请。

### 好友列表

对于希望允许每位用户的好友轻松加入而无需创建[一对一邀请](#one-to-one-invitations)的游戏,可以创建包含用户完整好友列表的邀请。

连接到网络后,每位用户创建 `PartyInvitationConfiguration` 结构,并将其每位社交平台好友添加到其 `entityIds` 字段。将此结构传给 `PartyNetwork::CreateInvitation()`,并将网络描述符和邀请标识符与好友共享。当用户的好友列表更改时,应撤销该邀请并使用新的好友列表创建新邀请。

### 动态单一邀请

许多游戏都有大厅或其他外部服务,用于控制谁应该加入给定网络。为使网络与外部服务保持同步,可以使用动态单一邀请模式。此模式使用具有众所周知标识符的单个邀请。

此模式有两种变体。外部服务可以选择单个用户来管理网络的邀请,或者可以要求所有用户尝试管理邀请。在这两种情况下,每当应处于网络中的用户集发生变化时,外部服务会通知用户,用户尝试撤销当前邀请并使用相同的众所周知标识符创建包含新的完整用户集的新邀请。

#### 单用户管理

让单个用户负责撤销当前邀请并创建新邀请可以带来邀请所有权的可预测性。然而,外部服务需要执行以下操作。

* 选择将管理邀请的用户。
* 当上一位用户离开网络时选择新用户。

#### 全用户管理

让所有用户尝试管理邀请会导致邀请所有权不可预测,但可避免外部服务需要选择单个用户。相反,每台设备上的用户执行以下操作。

* 尝试撤销当前邀请。对于初始邀请,所有用户都尝试这样做,但只有一位会成功。对于其他邀请,只有创建最新邀请的用户才能尝试撤销它,因为该邀请对其他用户不可见。
* 尝试创建新邀请。由于邀请必须具有唯一标识符,只有其中一位用户会成功。该用户必须通知其他人自己是新邀请所有者,因为该邀请在其他设备上不可见。
* 当当前邀请的创建者离开创建设备时,所有用户必须再次尝试创建新邀请。

<Info>
  在撤销邀请并使用相同标识符创建新邀请时,存在一个短暂时间窗口,邀请标识符是无效的。如果你使用此方法,在经过合理等待时间后,如果 `PartyNetwork::AuthenticateLocalUser()` 调用失败,则需要重试。
</Info>

### 滚动开放邀请

对于由大厅或其他外部服务控制谁应加入给定网络的游戏,除了[动态单一邀请](#dynamic-single-invitation)模式之外,另一种选择是滚动开放邀请模式。在此模式中,始终存在一个开放邀请。每当先前允许加入的用户从外部服务的用户列表中移除时,该邀请就会被撤销并以新的标识符重新创建。邀请标识符的作用类似于密码,应类似地予以保护。此模式可以通过以下步骤实现:

* 外部服务选择一个设备来创建网络,并指定要使用的邀请标识符。
* 外部服务将邀请标识符发送给所有其他应加入网络的用户。
* 当新用户应加入网络时,外部服务将当前邀请标识符与该用户共享。
* 当具有当前邀请的用户不再被允许加入时,外部服务需要通过执行以下操作来“更改密码”。
  * 选择新的邀请标识符。
  * 请求一位或所有用户撤销当前邀请并使用所选的邀请标识符创建新邀请。有关单用户管理与全用户管理的讨论,请参阅[动态单一邀请](#dynamic-single-invitation)。
  * 与现在应被允许加入网络的所有用户共享新的邀请标识符。

## 后续步骤

* [了解 PlayFab Party 如何与你的发现流程交互](/services/playfab/multiplayer/networking/concepts-discovery)


## Related topics

- [PlayFab Party 对象及其关系](/zh-CN/services/playfab/multiplayer/networking/concepts-objects.md)
- [使用 RequestPartyService 从服务端请求 party](/zh-CN/services/playfab/multiplayer/networking/party-tutorial-requestpartyservice.md)
- [PFGroupsListMembershipOpportunitiesRequest](/zh-CN/services/playfab/api-references/c/pfgroupstypes/structs/pfgroupslistmembershipopportunitiesrequest.md)
- [GDK 中的 Windows Sockets 简介](/zh-CN/build/console-features/networking/game-mesh/winsock-intro-networking.md)
- [Party 示例](/zh-CN/services/playfab/multiplayer/networking/party-samples.md)
