# 会话管理

**URL:** https://heroiclabs.com/docs/zh/nakama/concepts/session/management/
**Summary:** 了解 Nakama 中会话（玩家的设备、用户和社交帐户、行为）的定义与用法，以及如何在游戏中将这些概念分层，实现所需的玩家体验。

---


# 会话管理

身份验证，再加上用户帐户和会话管理，看上去很复杂。有许多活动的部分组合在一起，例如：

- 玩家行为
- 玩家设备
- 社交服务提供商帐户
- Nakama 用户帐户

人们总想马上开始编程，希望将一组不相关的概念拼凑在一起。这也行，但是您会在试错中走弯路，让自己（和玩家）感动到沮丧。

相反，我们可以将这些概念作为一个整体来处理，在您的代码和玩家的体验中对不同类型的会话（游戏、社交和身份验证）进行分层。

## 会话类型

*会话*一词用得过滥，在不同的环境中用于表示不同的事物，从抽象的游戏创意到游戏开发的低级机制，都包括在内。为了进行身份验证，我们关注三种类型：游戏、登录和身份验证会话。

还有其他类型的会话，并且对开发游戏身份验证技术有帮助（例如网络 TCP 会话或加密 TLS 会话）。对于本主题，让我们假设这些底层协议都能工作，更多地关注玩家交互。

### 游戏会话

游戏会话表示玩家玩游戏直至停止的时间。游戏会话及其时长随游戏类型、平台和玩家而变。它可能持续一个回合或一场比赛（或多个回合或多场比赛），并且可能受玩家的注意力持久性和动机的影响。

游戏会话是玩家对游戏的体验。

### 登录会话

登录会话表示玩家登录其帐户的时间。这通常是通过 Google Play Games、Apple Game Center 等提供商或您自己的帐户基础结构实现的。

登录会话是游戏区分玩家的方式。它是跟踪特定玩家的一种途径。

### 身份验证会话

登录会话表示客户端和服务器彼此进行可信通信的时间。您也可以将此视为 *Nakama 会话*。

## 会话重叠

玩家一般都没有想到自己的登录状态或服务器连接。他们只想到在玩和没在玩。他们不希望每次进入一个回合时都输入密码或面对“正在连接”屏幕。

因此，会话类型重叠，互相依赖。登录和身份验证这样支持游戏：它们比游戏会话运行的时间更长或更短，（有望）以对玩家透明的方式运行。

您可以想象你的游戏同时进行多个会话：玩家登录、玩家花时间玩游戏、客户端与 Nakam 连接。

![玩家行为与会话类型之间的重叠](images/sessions.png)

但会话类型并非彼此紧密联系。一个玩家每天可能只玩几分钟，但在其苹果帐户上保持登录几天或几周。根据游戏的不同，服务器连接可能会短暂而间歇性地建立，也可能会持续很长时间。会话需要随玩家和游戏活动而开始和结束。

## 开始会话

在客户端可以在服务器上执行任何操作（例如匹配或更新排行榜）之前，客户端必须通过与服务器的身份验证。

[身份验证](../../authentication/)标志着与 Nakama 会话的开始。通常，每次游戏开始您都进行身份验证。

Nakama 中的会话周期如下：

1. 开始会话。使用身份验证 API 识别玩家或设备，Nakama 用会话对象进行响应。

2. 用会话对象发出请求。

3. 会话过期后，需要时进行刷新或重新进行身份验证。

第一步是最复杂的。为了启动会话，您的客户端使用标识符请求身份验证。此 ID 可以来自许多来源：社交服务提供商的 OAuth令牌、设备 ID、用户名和密码，或者自己的自定义服务。
无论您的凭据来自哪里，它们都表示相同的意思：正在玩游戏的是此玩家或设备，而不是任何其他玩家或设备。

## 身份验证和社交平台个人资料

这是身份验证会话和登录会话层结合在一起的地方。身份验证将玩家的登录会话映射到 Nakama 会话。

通常，身份验证 API 使用的标识符是来自[社交服务提供商](../../authentication/#social-providers)（如 Apple Game Center、Google Play Games 或 Facebook）的令牌。

如果玩家未登录，此时游戏触发登录流程，获得一个新的标识符。如果玩家已登录，那么您将传入现有的标识符。

**当您使用玩家的登录 ID 进行身份验证时，您将玩家的登录标识映射到他们的 Nakama [用户帐户](../../user-accounts/)。** 这就是您开始将游戏会话、登录会话和身份验证会话结合在一起的方式。当您稍后想要获取用户数据时，可以通过 Nakama 用户 ID 或社交服务提供商 ID 进行查找。

## 提供会话对象

身份验证成功后，Nakama 通过一个特别会话对象回复：[JSON Web Token (JWT)](https://jwt.io/)。此会话对象就像有过期日期的建筑通行证。您需要它开门：向 Nakama 服务器提供进一步的请求。

JWT 是有加密签名的 JSON 对象。Nakama 会话对象 JWT 包含一些[详细信息](../../authentication/#session)（包括到期日期和时间），这些都已用[服务器私钥](../../../getting-started/configuration/#session.encryption_key)签名。

只要 JWT 未过期且未被篡改，服务器就可以安全地验证 JWT。同时，JWT *未*加密，因此客户端代码也可以检查其内容。

此例为编码形式的 JWT：

```bash
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJmNDA4MmFhMC1hYWQwLTQ1MjYtODkwZC1iYTUwYjI0NmJlMTkiLCJ1c24iOiJhS25pWU5pZ1FiIiwiZXhwIjoxNTk3NjY3MjIwfQ.1fdAmq3nrDcPy0k6BwPCcULmhLiB54Z_feEuDaINNsA
```

解码后成为这个 JSON 对象：

```json
{
    "uid": "f4082aa0-aad0-4526-890d-ba50b246be19",
    "usn": "aKniYNigQb",
    "exp": 1597667220
}
```

JWT 包含三个密钥：

- `uid` - 经过身份验证的 Nakama 用户的 ID（Nakama 的用户记录可能有一个或多个社交标识符，但这是 Nakama 对用户的唯一引用）
- `usn` - 用户名
- `exp` - Unix 时间戳格式的到期日期和时间

有了这个 JWT，您的代码将向 Nakama 提交每个新请求的 JWT（编码形式）。通过使用 JWT，对 Nakama 的请求都是轻量级的，服务器可以快速验证请求。由于有加密签名，Nakama 可以验证请求，而没有数据库查找所致的延迟。

换言之，将 JWT 缓存！只要您有有效的会话对象，就可以通过设置比赛、更新排行榜、将玩家添加到聊天组等方式支持游戏会话。

## 会话的结束方式

在 Nakama [配置](../../../getting-started/configuration/#session.token_expiry_sec)中设置的时间后，会话对象过期。如果尝试使用过期的会话对象发出请求，请求将被拒绝，并出现 `401 Unauthorized` 错误。

当它过期时，您不能向 Nakama 发出新的请求（尽管活动套接字连接会一直持续到关闭，即使原始令牌已过期）。如需继续发出请求，可以使用[有效刷新令牌](../../../getting-started/configuration/#session.refresh_token_expiry_sec)[刷新会话](../#session-refresh)。 

如果刷新令牌也过期了，则必须返回到起始位置并重新进行身份验证。

但这并不一定意味着登录会话或游戏会话同时结束。例如，如果您与 Game Center 的登录会话仍然有效，并且玩家仍然处于活动的玩游戏会话中，那么您可以重新进行身份验证，而不会错过一个节拍。您不必让玩家重新登录，或迫使他们退出游戏，然后再重新进行身份验证。

同样，会话结束并不意味着您必须立即重新进行身份验证。您可以等待玩家的下一次游戏会话，或者等待需要 Nakama 的特定游戏操作。

## 结束会话有用的原因

有时人工结束客户端上的会话有用处。例如，您可能希望通过这种方式让用户能够注销游戏、切换用户帐户或从设备中清除本地状态数据。

添加人工结束会话选项的一个重要原因是，有的情况下用户使用共享设备。人工结束会话，清除本地会话数据，将防止对用户帐户和游戏数据的未授权访问。

## 在游戏中建立会话管理功能

在游戏中建立多层不同种类的会话可能会让人感到复杂。但 Nakama 可以在低层细节方面为您提供帮助。

在服务器上，Nakama API 提供一般`authenticate` [终结点](https://heroiclabs.com/docs/concepts/authentication/#authenticate)，以及[Apple、Facebook、Google 和 Steam 专用的终结点](https://heroiclabs.com/docs/concepts/authentication/#social-providers)。

在客户端上，您可以使用专用于您的语言或引擎的 Nakama 客户端进行身份验证、刷新会话和配置自动会话管理。请看[身份验证示例](https://heroiclabs.com/docs/concepts/authentication/#authenticate)，进行深入了解。
