# C++ 集成

> Learn how to implement authentication using C++ in Unreal Engine.

以下部分展示如何使用 [Unreal Engine 子系统](https://docs.unrealengine.com/5.3/en-US/programming-subsystems-in-unreal-engine/)与 Authentication SDK 集成。Blueprint API 提供了 Authentication 子系统来公开此功能。

## 将 Authentication SDK 添加为依赖项##add-the-authentication-sdk-as-a-dependency

继续下一步前，请将 `Authentication` 添加为模块的公共依赖项，然后将插件头文件包含到您的类中。

将 `Authentication` 作为模块的依赖项添加到您的 Unreal 项目构建文件：

```cpp
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Authentication" });
```

将希望访问的插件头文件包含到您自己的类中：

```cpp
#include "AuthenticationSubsystem.h"
```

## Authentication 子系统##authentication-subsystem

Authentication 子系统包含用于与 Unity Authentication 服务器通信、保存玩家配置文件信息以及从本地存储中加载/卸载玩家偏好设置的接口。它负责处理身份验证生命周期并存储项目的重要身份验证信息。

您可以通过从 [UGameInstance](https://docs.unrealengine.com/5.3/en-US/API/Runtime/Engine/Engine/UGameInstance/) 获取引用来访问 Authentication 子系统。

```cpp
UWorld* GameWorld = GetWorld();
UGameInstance* GameInstance = GameWorld->GetGameInstance();
UAuthenticationSubsystem* AuthenticationSubsystem = GameInstance->GetSubsystem<UAuthenticationSubsystem>();
```

### SignInAnonymously##signinanonymously

使用 [SignInAnonymously()](./sdk-api/authentication/authentication-subsystem.md#signinanonymously\(fauthenticationsigninoptions,-unity::services::core::thandlerfauthenticationresponse\)) 方法进行[匿名验证](/authentication/use-anon-sign-in.md)。这是一种无需任何用户信息即可进行身份验证的快速方法，并且不需要与外部提供商进行交互。如果成功，这将使用从 Unity Authentication 服务器返回的凭据填充当前玩家配置文件。

[SignInAnonymously()](./sdk-api/authentication/authentication-subsystem.md#signinanonymously\(fauthenticationsigninoptions,-unity::services::core::thandlerfauthenticationresponse\)) 采用 [`FAuthenticationSignInOptions`](./sdk-api/authentication/models/authentication-sign-in-options.md) 结构作为参数来更改登录的执行方式。如需有关这些参数的更多信息，请参阅 [Unity API 服务文档页面](https://services.docs.unity.com/player-auth/v1/index.html)。

SDK 的响应可以在需要接受 [`FAuthenticationResponse`](./sdk-api/authentication/models/authentication-response.md) 的响应处理程序中处理。

```cpp
// Create sign-in options body
FAuthenticationSignInOptions SignInOptions;
SignInOptions.bCreateAccount = true;
SignInOptions.Nonce = TEXT("abc123");

AuthenticationSubsystem->SignInAnonymously(SignInOptions, THandler<FAuthenticationResponse>::CreateLambda([this](FAuthenticationResponse Response)
{
	// Your response logic here
}));
```

### GetUserInfo##getuserinfo

使用 [GetUserInfo()](./sdk-api/authentication/authentication-subsystem.md#getuserinfo\(unity::services::core::thandlerfauthenticationuserresponse\)) 方法检索有关当前经过身份验证的用户的信息。这包括他们的用户 ID、身份验证时间戳以及与他们的会话关联的任何外部身份提供商。

SDK 的响应可以在需要接受 [`FAuthenticationUserResponse`](./sdk-api/authentication/models/authentication-user-response.md) 的响应处理程序中处理。

```cpp
AuthenticationSubsystem->GetUserInfo(
THandler<FAuthenticationUserResponse>::CreateLambda([this](FAuthenticationUserResponse Response)
{
	// Your response logic here
}));
```

### DeleteUser##deleteuser

使用 [DeleteUser()](./sdk-api/authentication/authentication-subsystem.md#deleteuser\(unity::services::core::thandlerbool\)) 方法删除与当前经过身份验证的玩家相关的所有信息。此方法还会使玩家注销，并删除与该玩家关联的所有玩家首选项和配置文件。

> **Note:**
>
> 如果在使用默认配置文件时调用 [DeleteUser()](./sdk-api/authentication/authentication-subsystem.md#deleteuser\(unity::services::core::thandlerbool\))，则配置文件信息会被清除，配置文件保持不变。

SDK 的响应可以在需要接受 `bool` 的响应处理程序中处理：删除成功时其值为 `true`，否则为 `false`。

```cpp
AuthenticationSubsystem->DeleteUser(
THandler<bool>::CreateLambda([this](bool bResponse)
{
	// Your response logic here
}));
```

### RegisterStateChangedCallback##registerstatechangedcallback

使用 [RegisterStateChangedCallback()](./sdk-api/authentication/authentication-subsystem.md#registerstatechangedcallback\(unity::services::core::thandlerfauthenticationstatechangedresponse\)) 方法分配一个回调函数，该函数在[子系统的状态](./authentication-lifecycle.md)更改时调用。例如，当玩家成功进行身份验证并且子系统状态更改为 `Authorized` 时，将执行分配的函数。

SDK 的响应可以在需要接受 [`AuthenticationStateChangedResponse`](./sdk-api/authentication/models/authentication-state-changed-response.md) 的响应处理程序中处理。

```cpp
AuthenticationSubsystem->RegisterStateChangedCallback(
THandler<AuthenticationStateChangedResponse>::CreateLambda([this](AuthenticationStateChangedResponse Response)
{
	// Your response logic here
}));
```

### SignOut##signout

使用 [SignOut()](./sdk-api/authentication/authentication-subsystem.md#signout\(bool\)) 方法注销当前经过身份验证的玩家配置文件。这将移除当前玩家配置文件并切换到默认配置文件。此方法还有一个可选参数，用于移除任何先前存储的与该玩家相关的凭据。

> **Note:**
>
> 如果在使用默认配置文件时调用 [SignOut()](./sdk-api/authentication/authentication-subsystem.md#signout\(bool\))，则配置文件信息会被清除，配置文件保持不变。

```cpp
AuthenticationSubsystem->SignOut(true); // Clear player credentials
```

### SwitchProfile##switchprofile

使用 [SwitchProfile()](./sdk-api/authentication/authentication-subsystem.md#switchprofile\(const-fstring&\)) 方法切换到或创建玩家配置文件。

> **Note:**
>
> **注意**：仅在已注销的状态下才可以调用 [SwitchProfile()](./sdk-api/authentication/authentication-subsystem.md#switchprofile\(const-fstring&\))。如果在经过身份验证时调用配置文件切换，则会记录一条警告，并且不会发生任何改变。

```cpp
FString NewProfileName = FString(TEXT("new_profile_123"));
AuthenticationSubsystem->SwitchProfile(NewProfileName);
```

### ProfileExists##profileexists

使用 [ProfileExists()](./sdk-api/authentication/authentication-subsystem.md#profileexists\(const-fstring&\)) 方法检查是否存在玩家配置文件。

> **Note:**
>
> **注意**：[ProfileExists()](./sdk-api/authentication/authentication-subsystem.md#profileexists\(const-fstring&\)) 无法检测到在先前会话中存在但在当前会话中尚未重新创建的配置文件。

```cpp
FString ProfileToCheckFor = FString(TEXT("new_profile_123"));
bool bExists = AuthenticationSubsystem->ProfileExists(ProfileToCheckFor);
```

### GetCurrentProfileName##getcurrentprofilename

使用 [GetCurrentProfileName()](./sdk-api/authentication/authentication-subsystem.md#getcurrentprofilename\(\)) 方法检索当前玩家配置文件的名称。

```cpp
FString ProfileName = AuthenticationSubsystem->GetCurrentProfileName();
```

### GetProfileNames##getprofilenames

使用 [GetCurrentProfileName()](./sdk-api/authentication/authentication-subsystem.md#getcurrentprofilename\(\)) 方法获取当前会话中使用的所有玩家配置文件名称的列表。

```cpp
TArray<FString> ProfileNames = AuthenticationSubsystem->GetProfileNames();
```

### RegisterProfileChangedCallback##registerprofilechangedcallback

使用 [RegisterProfileChangedCallback()](./sdk-api/authentication/authentication-subsystem.md#registerprofilechangedcallback\(unity::services::core::thandlerfauthenticationplayerprofilechangedresponse\)) 方法分配一个回调函数，该函数在玩家配置文件更改时调用。例如，当调用 [SwitchProfile](./cpp-integration.md#switchprofile) 或注册的配置文件被删除时，将调用分配的函数。

SDK 的响应可以在需要接受 [AuthenticationPlayerProfileChangedResponse](./sdk-api/authentication/models/authentication-player-profile-changed-response.md) 的响应处理程序中处理。

```cpp
AuthenticationSubsystem->RegisterPlayerProfileChangedCallback(
THandler<AuthenticationPlayerProfileChangedResponse>::CreateLambda([this](AuthenticationPlayerProfileChangedResponse Response)
{
	// Your response logic here
}));
```

### RegisterProfileDeletedCallback##registerprofiledeletedcallback

使用 [RegisterProfileChangedCallback()](./sdk-api/authentication/authentication-subsystem.md#registerprofilechangedcallback\(unity::services::core::thandlerfauthenticationplayerprofilechangedresponse\)) 方法分配一个回调函数，该函数在删除玩家配置文件时调用。例如，当调用 [SignOut](./cpp-integration.md#signout) 或 DeleteUser 时，将调用分配的函数。

SDK 的响应可以在需要接受 [AuthenticationPlayerProfileChangedResponse](./sdk-api/authentication/models/authentication-player-profile-changed-response.md) 的响应处理程序中处理。

```cpp
AuthenticationSubsystem->RegisterPlayerProfileChangedCallback(
THandler<AuthenticationPlayerProfileChangedResponse>::CreateLambda([this](AuthenticationPlayerProfileChangedResponse Response)
{
	// Your response logic here
}));
```

### IsSignedIn##issignedin

使用 [IsSignedIn()](./sdk-api/authentication/authentication-subsystem.md#issignedin\(\)) 方法检查当前玩家配置文件是否已登录。“Signed-In（已登录）”状态的定义为 Authorized（已授权）或 Expired（已到期）。

```cpp
bool bSignedIn = AuthenticationSubsystem->IsSignedIn();
```

### IsAnonymous##isanonymous

使用 [IsAnonymous()](./sdk-api/authentication/authentication-subsystem.md#isauthorized\(\)) 方法检查当前玩家配置文件是否匿名登录。成功执行 [SignInAnonymously](./cpp-integration.md#signinanonymously) 后，这应该返回 true。

```cpp
bool bAnonymous = AuthenticationSubsystem->IsAnonymous();
```

### IsAuthorized##isauthorized

使用 [IsAuthorized()](./sdk-api/authentication/authentication-subsystem.md#isauthorized\(\)) 方法检查当前玩家配置文件是否已登录并且当前已获得授权。在到期时间未过的情况下成功执行任何登录方法后都应返回 true。

```cpp
bool bAuthorized = AuthenticationSubsystem->IsAuthorized();
```

### IsExpired##isexpired

使用 [IsExpired()](./sdk-api/authentication/authentication-subsystem.md#isexpired\(\)) 方法检查当前玩家配置文件的会话是否已到期。当成功登录响应返回的有效期已过后，这应该返回 true。

```cpp
bool bExpired = AuthenticationSubsystem->IsExpired();
```

### SessionTokenExists##sessiontokenexists

使用 [SessionTokenExists()](./sdk-api/authentication/authentication-subsystem.md#sessiontokenexists\(\)) 方法检查当前配置文件是否存储了现有会话令牌。

```cpp
bool bTokenExists = AuthenticationSubsystem->SessionTokenExists();
```

### GetUnityProjectId##getunityprojectid

使用 [GetUnityProjectId()](./sdk-api/authentication/authentication-subsystem.md#getunityprojectid\(\)) 方法检索当前的 Unity Project ID。

```cpp
FGuid ProjectId = AuthenticationSubsystem->GetUnityProjectId();
```

### GetUnityEnvironmentName##getunityenvironmentname

使用 [GetUnityEnvironmentName()](./sdk-api/authentication/authentication-subsystem.md#getunityenvironmentname\(\)) 方法检索当前的 Unity 环境名称。

```cpp
FString EnvironmentId = AuthenticationSubsystem->GetUnityEnvironmentName();
```

### GetAccessToken##getaccesstoken

使用 [GetAccessToken()](./sdk-api/authentication/authentication-subsystem.md#getaccesstoken\(\)) 方法获取当前会话的访问令牌。如果不存在，此函数返回一个空字符串。

```cpp
FString AccessToken = AuthenticationSubsystem->GetAccessToken();
```

### GetSessionToken##getsessiontoken

使用 [GetSessionToken()](./sdk-api/authentication/authentication-subsystem.md#getsessiontoken\(\)) 方法获取当前会话的会话令牌。如果不存在，此函数返回一个空字符串。

```cpp
FString SessionToken = AuthenticationSubsystem->GetSessionToken();
```

### GetUserId##getuserid

使用 [GetUserId()](./sdk-api/authentication/authentication-subsystem.md#getuserid\(\)) 方法获取当前会话的用户 ID。如果不存在，此函数返回一个空字符串。

> **Note:**
>
> **注意**：这与[玩家配置文件名称](./cpp-integration.md#getcurrentprofilename)不同。用户 ID 是从 Unity Authentication 系统返回的唯一用户标识符。

```cpp
FString UserId = AuthenticationSubsystem->GetUserId();
```

### GetState##getstate

使用 [GetState()](./sdk-api/authentication/authentication-subsystem.md#getstate\(\)) 方法获取身份验证会话的当前状态。

```cpp
EAuthenticationState UserId = AuthenticationSubsystem->GetUserId();
```

### SetUnityProjectId##setunityprojectid

使用 [SetUnityProjectId()](./sdk-api/authentication/authentication-subsystem.md#setunityprojectid\(fguid\)) 方法设置当前身份验证会话的 Unity Project ID。这将覆盖在项目设置中配置的 Unity Project ID。

```cpp
FGuid NewProjectId = FGuid(TEXT("00000000-1234-1234-000000000000"));
AuthenticationSubsystem->SetUnityProjectId(NewProjectId);
```

### SetUnityEnvironmentName##setunityenvironmentname

使用 [SetUnityEnvironmentName()](./sdk-api/authentication/authentication-subsystem.md#setunityenvironmentname\(fstring\)) 方法设置当前身份验证会话的 Unity 环境名称。这将覆盖在项目设置中配置的 Unity 环境名称。

```cpp
FString NewEnvironmentName = FString(TEXT("testenv2"));
AuthenticationSubsystem->SetUnityEnvironmentName(NewEnvironmentName );
```
