访问控制

Unity Gaming Services(Unity 游戏服务)(UGS) 的访问控制功能可以保护 UGS 中的游戏状态和逻辑免受作弊者和攻击者的侵害。访问控制(也称为 API 授权)可以让您控制谁有权访问、修改或删除游戏数据和资源,以保护游戏免受未经授权的访问,因此非常重要。

UGS 的 API 授权是确定用户在经过身份验证后可以执行哪些操作的过程。身份验证可以验证用户的真实身份。身份验证和授权相结合,提供了一种控制 API 访问和资源访问的安全方法。UGS 提供了与本文档中所述的 API 授权配合使用的 Authentication 解决方案。

如果没有身份验证,任何人都可以访问 API 并可能执行未经授权的操作。例如,如果 API 允许用户查看敏感信息或更改数据,但没有设置身份验证,那么任何人都可以访问这些信息或在未经许可的情况下进行更改。

身份验证是为了确定用户的身份,而授权是为了控制用户可以执行的操作。身份验证为执行授权提供了必要的基础。身份验证就像是打开 API 大门的钥匙,而授权则决定用户是否被允许进门,以及进门后可以做什么。

访问控制的工作原理

UGS 中的访问控制是使用资源策略进行配置的。UGS 服务强制执行一些规则,规定谁可以访问这些服务以及他们可以执行哪些操作。

当用户尝试访问某个 UGS 服务时,该服务会根据配置的策略检查用户的身份,然后决定拒绝还是允许 API 请求。

一个资源策略是一系列语句的集合。这些语句按照用户的身份(Principal 属性)、限制或允许(Effect 属性)的操作(Action 属性)以及策略适用的资源(Resource 属性)进行定义。策略还包含“Sid”属性(语句标识符),这是用户为给定策略定义的描述性名称,只能包含字母数字字符和连字符。

策略中的资源被定义为统一资源名称 (URN),通常以构成 URN 组成部分的 API 路径结尾。

资源策略是根据每个项目或每个玩家进行配置的。项目策略将针对该项目中所有调用 UGS 服务的主体接受评估。玩家策略仅针对项目和环境范围内的单个玩家接受评估。

以下是 Economy 服务的一个有效 URN 的示例:

urn:ugs:economy:/v2/project/*/player/*/currencies/gold

此处使用 glob 模式来匹配一组共用某种模式的资源。以下是此 URN 的不同组成部分。

URN 组成部分描述
urn:此前缀表明该字符串是 URN。
ugs:URN 的命名空间标识符 (NID),用于标识负责维护此命名空间中的 URN 的组织或组。在此例中,“ugs”代表 Unity Gaming Services(Unity 游戏服务),是创建此 URN 的组。
economy:命名空间内的特定命名机构,用于标识 UGS 的特定区域。
/v2/project/URN 的特定分段,用于标识 API 的版本以及 URN 适用的项目。
*第一个与任意字符匹配的 glob 模式。这是一个代表任何可能值的通配符。在此例中,它将匹配以“urn:ugs:economy:/v2/project/”开头且后跟任意字符的任何 URN。
/player/URN 的特定分段,用于标识 URN 适用的玩家。
*第二个与任意字符匹配的 glob 模式。在此例中,它将匹配以“urn:ugs:economy:/v2/project/*/player/”开头且后跟任意字符的任何 URN。
/currencies/gold这是 URN 的特定分段,用于标识 URN 适用的特定货币类型。

由于 URN 匹配过程使用 glob 模式,因此上述 URN 也可以定义如下。

urn:ugs:economy:/**/currencies/gold

当未创建访问控制策略时,访问控制默认为允许经过身份验证的玩家的所有经过身份验证的 API 调用。这种情况可以用以下资源策略来进行描述。

{
	"Sid": "allow-all-ugs",
	"Effect": "Allow",
	"Action": ["*"],
	"Principal": "Player",
	"Resource": "urn:ugs:*"
},

以下示例显示了如何创建有效的策略,以允许经过身份验证的玩家通过 API 调用读取但不能更改(写入)Economy 中的黄金货币。

{
	"Sid": "deny-economy-write-access",
	"Effect": "Deny",
	"Action": ["Write"],
	"Principal": "Player",
	"Resource": "urn:ugs:economy:/v2/project/*/player/*/currency/gold"
},

或者,若要完全拒绝经过身份验证的玩家访问 Economy 中的所有 API,可以创建以下策略:

{
	"Sid": "deny-all-economy-access",
	"Effect": "Deny",
	"Action": ["*"],
	"Principal": "Player",
	"Resource": "urn:ugs:economy:*"
},

如何使用访问控制

使用 REST APIUGS CLI 为 UGS 创建资源策略。这些策略只需创建一次,并在经过身份验证的调用方的上下文中针对 UGS 的每个 API 调用进行评估和执行。

示例策略

不允许玩家执行任何 Cloud Code 脚本:

{
	"Sid": "deny-cloud-code-access",
	"Effect": "Deny",
	"Action": ["*"],
	"Principal": "Player",
	"Resource": "urn:ugs:cloud-code:/v1/projects/*/scripts/*"
},

此资源策略在玩家经过身份验证的项目中拒绝 Cloud Code 脚本的所有操作。Cloud Code 仅提供“执行”API 作为对该 API 的 POST 请求,这属于上述策略语句中的“写入”操作。

以下是 Cloud Save 资源策略的另一个示例:

{
	"Sid": "deny-cloud-save-data-write-access",
	"Effect": "Deny",
	"Action": ["Write"],
	"Principal": "Player",
	"Resource": "urn:ugs:cloud-save:/v1/data/projects/*/players/*/items**"
},

此资源策略拒绝任何经过身份验证的玩家对项目的所有 Cloud Save 数据进行写入访问,包括具有 Player 身份的用户或组对项下所有嵌套路径和子文件夹的写入访问。此策略实际上会阻止玩家直接将数据写入 Cloud Save。通过将此策略与先前的 Cloud Code 策略相结合,意味着开发者可以通过 Cloud Code 将数据写入 Cloud Save,并在 Cloud Code 中实现任何其他游戏逻辑。

以下说明了构成策略的不同组成部分及其作用。

语句属性可接受的值描述
Sid字母数字字符串,例如 ^[A-Za-z0-9][A-Za-z0-9_-]{5,59}$语句标识符。在此策略的每个环境中具有唯一性,用于提供人类可读的策略名称。有效值必须包含 5 到 59 个字符。例如,deny-cloud-save-data-write-access
EffectAllow、Deny用于指定此策略是允许还是拒绝对指定资源的访问。
操作Write、Read、*用于指定允许或拒绝的访问类型。这些操作针对 UGS 中的各种产品。
Write 值通常指一些会改变 UGS 服务状态的操作。UGS API 的 POST、PUT、PATCH、DELETE HTTP 动词属于此类别。
Read 值通常指一些从 UGS 服务中获取状态的操作。UGS API 的 GET HTTP 动词属于此类别。
* 值表示包括所有可接受的操作。
Principal玩家用于指定策略适用的用户身份。当前唯一可接受的值是“Player”。
Resource有效的 UGS URN用于指定策略适用的一个或多个资源。例如,可以将资源设置为 urn:ugs:cloud-save:/v1/data/projects/*/players/*/items**,这是一个具有 glob 模式的 URN,用于匹配项目中经过身份验证的玩家的 Cloud Save 数据,包括项下的所有嵌套路径和子路径。

错误响应

当玩家尝试访问他们没有适当权限的资源时,系统将返回错误响应,状态代码为 403 Forbidden。错误响应的具体格式取决于现有访问控制策略的类型。

如果按照基于项目的策略限制玩家访问资源,则错误响应包括以下字段:

{
  "title": "Forbidden",
  "detail": "Access has been restricted",
  "code": 56,
  "status": 403,
  "type": "https://services.docs.unity.com/docs/errors/#56"
}

如果按照基于玩家的策略限制玩家访问资源,则错误响应包括以下字段:

{
  "title": "Forbidden",
  "detail": "Principal is not authorized to access resource",
  "code": 57,
  "status": 403,
  "type": "https://services.docs.unity.com/docs/errors/#57"
}

如果玩家被暂时封禁,错误响应还会包含一个 expiresAt 字段,指明封禁到期时间:

{
  "title": "Forbidden",
  "detail": "Principal is not authorized to access resource",
  "code": 57,
  "status": 403,
  "type": "https://services.docs.unity.com/docs/errors/#57",
  "expiresAt": "2023-04-29T18:30:51.243Z"
}

如果玩家被永久封禁,错误响应将不包含 expiresAt 字段。您应该在应用程序代码中适当处理这些错误响应,以确保流畅的用户体验。

访问控制的策略选择

在评估访问控制策略时,只有最具体的规则才会胜出,并应用其效果。

以下是三个策略示例。

{
	"Sid": "deny-all-economy-access",
	"Effect": "Deny",
	"Action": ["*"],
	"Principal": "Player",
	"Resource": "urn:ugs:economy:*"
},
{
	"Sid": "allow-economy-currencies-access",
	"Effect": "Allow",
	"Action": ["*"],
	"Principal": "Player",
	"Resource": "urn:ugs:economy:/v2/**/currencies/*"
},
{
	"Sid": "deny-gold-currency-access-economy",
	"Effect": "Deny",
	"Action": ["Write"],
	"Principal": "Player",
	"Resource": "urn:ugs:economy:/v2/**/currencies/gold"
},
  1. 第一条规则是对 Economy 的所有请求的通用拒绝规则
  2. 第二条规则允许对 Economy 中 */currencies/ API 的所有请求进行读写访问
  3. 第三条规则明确拒绝对 Economy 中 */currencies/gold API 的写入请求进行访问

如果对 */currencies/silver 发出请求,则会应用第二条规则,即允许 /currencies/*,因为这条规则比第一条规则更具体。

如果对 */currencies/gold 发出请求,则会应用第三条规则,即拒绝 */currencies/gold,因为这条规则是与请求匹配的最具体规则。

如果有多个策略列出完全相同的 Resource,则 Deny Effect 始终优先。

最佳实践

默认拒绝

首先采用默认策略拒绝所有访问,然后显式授予对特定 API 或资源的访问。

{
	"Sid": "deny-all-ugs-access",
	"Effect": "Deny",
	"Action": ["*"],
	"Principal": "Player",
	"Resource": "urn:ugs:*:/**"
},

最低权限原则

仅授予 API 或资源所需的最低权限。

{
	"Sid": "allow-cloud-save-read-access",
	"Effect": "Allow",
	"Action": ["Read"],
	"Principal": "Player",
	"Resource": "urn:ugs:cloud-save:/v1/data/**/player/*/items**"
},

定义精细策略

为特定的 API 方法和资源创建策略,而不是为所有 API 和资源创建策略。

{
	"Sid": "allow-economy-silver-readwrite-access",
	"Effect": "Allow",
	"Action": ["*"],
	"Principal": "Player",
	"Resource": "urn:ugs:economy:/**/currencies/silver"
},
{
	"Sid": "deny-economy-gold-write-access",
	"Effect": "Deny",
	"Action": ["Write"],
	"Principal": "Player",
	"Resource": "urn:ugs:economy:/**/currencies/gold"
},

定期审查

定期审查和更新 API 策略,以确保策略反映游戏的当前状态,并移除不必要的权限。

REST API

访问控制 API 可以通过 Web 终端或 REST API 进行访问。REST API 提供更大的灵活性,让您可以利用喜欢的语言和游戏开发引擎来自动执行工作流程。

请参阅访问控制 REST API 文档以了解更多信息。请参阅服务帐户身份验证文档以详细了解如何对 API 调用进行身份验证。

以下示例显示了如何使用 REST API 与 cURL 工具来设置资源策略。

curl -X PATCH https://services.api.unity.com/access/v1/projects/{projectId}/environments/{environmentId}/resource-policy \
--header 'Authorization: Basic YOUR_ENCODED_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '
{
     "statements": [
    	{
            	"Sid": "deny-cloud-save-write-access",
            	"Effect": "Deny",
            	"Action": ["Write"],
            	"Principal": "Player",
            	"Resource": "urn:ugs:cloud-save:*"
    	}
    ]
}'

部署访问控制配置

要应用您的配置,必须将配置部署到访问控制服务。

使用编辑器进行部署

要在 Unity 编辑器中部署访问控制配置,必须先安装所需的包,然后将 Unity Gaming Services(Unity 游戏服务)项目关联到 Unity 编辑器。

关联项目

Unity Gaming Services(Unity 游戏服务)项目与 Unity 编辑器关联。您可以在 Unity Cloud Dashboard 中找到您的 UGS Project ID。

  1. 在 Unity 编辑器中,选择 Edit(编辑)> Project Settings(项目设置)> Services(服务)

  2. 关联您的项目。

    • 如果项目没有 Unity Project ID:

      1. 选择 Create a Unity Project ID(创建 Unity Project ID)> Organizations(组织),然后从下拉菜单中选择一个组织。
      2. 选择 Create project ID(创建 Project ID)
    • 如果已有 Unity Project ID:

      1. 选择 Use an existing Unity project ID(使用现有 Unity Project ID)
      2. 从下拉菜单中选择组织和项目。
      3. 选择 Link project ID(关联 Project ID)

此时将显示您的 Unity Project ID,并且项目现在已关联到 Unity 服务。此外,还可以使用 UnityEditor.CloudProjectSettings.projectId 在 Unity 编辑器脚本中访问您的 Project ID。

安装所需的包

要在编辑器中创建访问控制配置,必须安装以下包:

请查看 Unity - 手册:Package Manager(包管理器)窗口,熟悉 Unity Package Manager(包管理器)界面。

安装这些包并将它们添加到可用包列表中:

  1. 在 Unity 编辑器的 Package Manager(包管理器)窗口中,选择 +(添加)> Add package by name...(按名称添加包...)
  2. 输入 com.unity.services.deployment
  3. 选择 Add(添加)
  4. com.unity.services.tooling 重复以上步骤。

创建配置

请按照以下步骤创建访问控制配置:

  1. 在 Unity 编辑器中,右键单击 Project(项目)窗口,然后选择 Create(创建)> Services(服务)> Access Control Configuration(访问控制配置)
  2. 根据需要为配置命名。
  3. Enter(输入)

现在,新配置会显示在 Project(项目)窗口和 Deployment(部署)窗口中;可通过选择 Window(窗口)> **Deployment(部署)**来访问 Deployment(部署)窗口。

编辑配置

有两种方法可以编辑现有的访问控制配置:

  • 在 Project(项目)选项卡中,双击现有配置。
  • 在 Deployment(部署)窗口中,找到现有配置,然后从右键单击菜单中选择 Open(打开)

使用 CLI 进行部署

使用 UGS 访问控制 CLI 可以更轻松地管理和自动进行访问控制配置。

配置 UGS CLI

按照以下步骤操作以开始使用 UGS CLI:

  1. 安装 UGS CLI
  2. 按如下方式配置 Project ID 和环境:
    ugs config set project-id <your-project-id>
    ugs config set environment-name <your-environment-name>
  3. 为服务帐户配置访问控制环境管理所需的角色。请参阅接受身份验证

部署资源

运行以下命令:

ugs deploy <path-to-access-control-file>