访问控制

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

UGS 的 API 授权是指在用户通过身份验证后确定其允许执行的操作的过程。身份验证会验证用户是否是其所声称的人。身份验证和授权共同提供了一种安全的方式来控制对 API 和资源的访问。UGS 提供了一个身份验证解决方案,该解决方案可与本文档中描述的 API 授权配合使用。

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

身份验证建立用户的身份,而授权控制他们允许执行的操作。身份验证为授权工作提供了必要的基础。它就像一把钥匙,可以打开 API 的大门,但授权决定是否允许用户进入,以及他们在进入后可以做什么。

访问控制的工作原理

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

当用户尝试访问 UGS 服务时,该服务会根据配置的策略检查用户的身份,并拒绝或允许 API 请求。

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

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

资源策略是按项目或按玩家配置的。项目策略针对调用该项目的 UGS 服务的所有主体进行评估。玩家策略仅针对项目和环境范围内的一名玩家进行评估。

以下是经济系统服务中有效 URN 的示例

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

它使用通配符模式来匹配一组共享共同模式的资源。以下是该 URN 的不同组成部分。

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

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

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

如果未创建访问控制策略,则访问控制默认允许来自已通过身份验证的玩家的所有已通过身份验证的 API 调用。可以使用以下资源策略来描述这种情况。

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

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

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

或者,要完全拒绝已通过身份验证的玩家访问经济系统中的所有 API

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

如何使用访问控制

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

示例策略

不允许玩家执行任何云代码脚本

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

此资源策略拒绝对玩家已通过身份验证的项目中云代码脚本上的所有操作的访问。云代码仅提供一个“execute”API 作为对该 API 的 POST 请求,该请求属于上述策略语句中的“Write”操作。

以下是云存档的资源策略示例

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

此资源策略拒绝对任何已通过身份验证的玩家写入项目的云存档数据,包括用户或具有“玩家”身份的组的项目下所有嵌套路径和子文件夹。这有效地防止了玩家直接向云存档写入数据。将此策略与之前的云代码策略相结合,意味着开发人员可以通过云代码将数据写入云存档,并在云代码中实现任何额外的游戏逻辑。

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

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

错误响应

当玩家尝试访问他们没有适当权限的资源时,将返回状态代码为 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),因为它是与请求匹配的最具体的规则。

如果有多个策略列出了完全相同的资源,则拒绝效果始终优先。

最佳实践

默认拒绝

从拒绝所有访问的默认策略开始,并显式授予对特定 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 调用进行身份验证的更多信息,请参阅服务帐户身份验证文档

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

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 游戏服务项目链接到 Unity 编辑器。

将您的Unity 游戏服务项目与 Unity 编辑器链接。您可以在 Unity 云仪表板中找到您的 UGS 项目 ID。

  1. 在 Unity 编辑器中,选择编辑 > 项目设置 > 服务

  2. 链接您的项目。

    • 如果您的项目没有 Unity 项目 ID

      1. 选择创建 Unity 项目 ID > 组织,然后从下拉菜单中选择一个组织。
      2. 选择创建项目 ID
    • 如果您有现有的 Unity 项目 ID

      1. 选择使用现有的 Unity 项目 ID
      2. 从下拉菜单中选择一个组织和一个项目。
      3. 选择链接项目 ID

您的 Unity 项目 ID 将出现,并且该项目现在已链接到 Unity 服务。您还可以使用 UnityEditor.CloudProjectSettings.projectId 在 Unity 编辑器脚本中访问您的项目 ID。

安装所需的软件包

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

Check Unity - Manual: Package Manager window to familiarize yourself with the Unity Package Manager interface.

要安装这些软件包并将它们添加到您的可用软件包列表中

  1. 在 Unity 编辑器的“包管理器”窗口中,选择+(添加) > 按名称添加包…
  2. 输入 com.unity.services.deployment
  3. 选择添加
  4. com.unity.services.tooling 重复这些步骤。

创建配置

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

  1. 在 Unity 编辑器中,右键单击“项目”窗口,然后选择创建 > 访问控制配置
  2. 随意命名配置。
  3. 回车键

现在,新配置在“项目”窗口和“部署”窗口中可见,可通过选择窗口 > 部署来访问。

编辑配置

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

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

使用 CLI 进行部署

使用UGS 访问控制 CLI可以更简单地管理和自动化您的访问控制配置。

配置 UGS CLI

请按照以下步骤开始使用 UGS CLI

  1. 安装 UGS CLI.
  2. 按如下方式配置您的项目 ID 和环境
    ugs config set project-id <您的项目 ID>
    ugs config set environment-name <您的环境名称>
  3. 使用访问控制环境管理所需角色配置服务帐户。请参阅进行身份验证

部署资源

运行以下命令

ugs deploy <访问控制文件路径>