访问控制
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 API 或 UGS 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 。 |
Effect | Allow、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"
},
- 第一条规则是对 Economy 的所有请求的通用拒绝规则
- 第二条规则允许对 Economy 中
*/currencies/
API 的所有请求进行读写访问 - 第三条规则明确拒绝对 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。
在 Unity 编辑器中,选择 Edit(编辑)> Project Settings(项目设置)> Services(服务)。
关联您的项目。
如果项目没有 Unity Project ID:
- 选择 Create a Unity Project ID(创建 Unity Project ID)> Organizations(组织),然后从下拉菜单中选择一个组织。
- 选择 Create project ID(创建 Project ID)。
如果已有 Unity Project ID:
- 选择 Use an existing Unity project ID(使用现有 Unity Project ID)。
- 从下拉菜单中选择组织和项目。
- 选择 Link project ID(关联 Project ID)。
此时将显示您的 Unity Project ID,并且项目现在已关联到 Unity 服务。此外,还可以使用 UnityEditor.CloudProjectSettings.projectId
在 Unity 编辑器脚本中访问您的 Project ID。
安装所需的包
要在编辑器中创建访问控制配置,必须安装以下包:
请查看 Unity - 手册:Package Manager(包管理器)窗口,熟悉 Unity Package Manager(包管理器)界面。
安装这些包并将它们添加到可用包列表中:
- 在 Unity 编辑器的 Package Manager(包管理器)窗口中,选择 +(添加)> Add package by name...(按名称添加包...)。
- 输入
com.unity.services.deployment
。 - 选择 Add(添加)。
- 对
com.unity.services.tooling
重复以上步骤。
创建配置
请按照以下步骤创建访问控制配置:
- 在 Unity 编辑器中,右键单击 Project(项目)窗口,然后选择 Create(创建)> Services(服务)> Access Control Configuration(访问控制配置)。
- 根据需要为配置命名。
- 按 Enter(输入)。
现在,新配置会显示在 Project(项目)窗口和 Deployment(部署)窗口中;可通过选择 Window(窗口)> **Deployment(部署)**来访问 Deployment(部署)窗口。
编辑配置
有两种方法可以编辑现有的访问控制配置:
- 在 Project(项目)选项卡中,双击现有配置。
- 在 Deployment(部署)窗口中,找到现有配置,然后从右键单击菜单中选择 Open(打开)。
使用 CLI 进行部署
使用 UGS 访问控制 CLI 可以更轻松地管理和自动进行访问控制配置。
配置 UGS CLI
按照以下步骤操作以开始使用 UGS CLI:
- 安装 UGS CLI。
- 按如下方式配置 Project ID 和环境:
ugs config set project-id <your-project-id>
ugs config set environment-name <your-environment-name>
- 为服务帐户配置访问控制和环境管理所需的角色。请参阅接受身份验证。
部署资源
运行以下命令:
ugs deploy <path-to-access-control-file>