メインコンテンツまでスキップ

プレイヤー検証をゲームセッションに統合する

Last updated on February 4, 2026

注釈:本資料はAI技術を用いて翻訳されています。

概要

AccelByte Gaming Services (AGS) Session には、専用サーバー (DS) によって維持されるゲームセッションにプレイヤーが入る際のセキュリティレベルを強化するゲームセッションプレイヤー検証機能が含まれています。DS は、接続を試みるゲームクライアントが有効なユーザーとして認証され、セッションのメンバーであることを確認する必要があります。プロセスは次のように動作します。

  • セッションサービスがシークレットキーを生成し、それを所持すべきプレイヤーに返します。
  • ゲームクライアントが DS への接続を試みると、サーバーはプレイヤーのユーザー ID に基づいてシークレットキーを検証します。
  • 検証が完了すると、プレイヤーのゲームクライアントは DS に正常に接続できます。

この記事では、ゲームクライアントと DS の両側での AGS Session のプレイヤー検証機能の実装について説明します。

前提条件

この記事の手順を完了するには、以下が必要です。

  • AGS Admin Portal へのアクセス。
  • マッチの設定に関する知識。
  • ゲームセッションの設定と参加に関する知識。

フローとコードスニペット

セッションプレイヤー検証の実装プロセスを説明しやすくするために、DS とゲームクライアントの 2 つの部分で構成されていると考えることができます。DS 側では、この記事ではサーバーがシークレットを生成する方法を説明します。ゲームクライアント側では、この記事ではシークレットを取得する方法を説明します。これは、ゲームセッションに参加するか、マッチメイキングを通じてセッションを作成することで発生する可能性があり、ロビーで接続の問題が発生した場合にシークレットを取得する方法も含まれます。

ゲームサーバー

マッチメイキングが正常にマッチを見つけると、ゲームセッションが作成され、専用サーバーが割り当てられます。その後、ゲームサーバーは、AGS Session からの DS Hub WebSocket 接続を介してシークレットの通知を受け取ります。

void AMyActor::ConnectToDSHub()
{
...
const AccelByte::GameServerApi::FOnV2SessionSecretUpdateNotification
OnDSHubSessionSecreteUpdateNotificationDelegate =
AccelByte::GameServerApi::FOnV2SessionSecretUpdateNotification::CreateUObject(this, &AMyActor::OnDSHubSessionSecreteUpdateNotification);
ServerApiClient->ServerDSHub.SetOnV2SessionSecretUpdateNotification(OnDSHubSessionSecreteUpdateNotificationDelegate);
...
ServerApiClient->ServerDSHub.Connect(ServerName);
}

void AMyActor::OnDSHubSessionSecreteUpdateNotification(const FAccelByteModelsSessionSecretUpdateNotification& Notification)
{
UE_LOG(LogTemp, Log, TEXT("DS SessionSecreteUpdate, Secret:%s"), *Notification.Secret);
}

ゲームクライアント

ゲームクライアントは、ゲームセッションに参加するか、マッチメイキングを通じてセッションを作成することでシークレットを取得できます。また、ロビーで接続の問題が発生した場合の対処方法も知ることができます。

マッチメイキングを開始するか、ゲームセッションに参加してセッションを正常に取得した後、ゲームクライアントは、ロビー WebSocket 接続を介してシークレットの通知を受け取ります。

void AMyActor::ConnectToLobby()
{
...
const AccelByte::Api::Lobby::FV2SessionJoinedSecretNotif V2SessionJoinedSecretNotifDelegate =
AccelByte::Api::Lobby::FV2SessionJoinedSecretNotif::CreateUObject(this, &AMyActor::OnV2SessionJoinedSecretNotif); ApiClient->Lobby.SetV2SessionJoinedSecretNotifDelegate(V2SessionJoinedSecretNotifDelegate);
...
ApiClient->Lobby.Connect();
}

void AMyActor::OnV2SessionJoinedSecretNotif(const FAccelByteModelsV2SessionJoinedSecret& Data)
{
UE_LOG(LogTemp, Log, TEXT("Client OnV2SessionJoinedSecretNotif, Secret=%s"), *Data.Secret);
}

マッチメイキングの開始

ゲームクライアントは、マッチメイキングを開始することで通知を受け取ることができます。

void AMyActor::CreateMatchTicket(const FString& SessionId)
{
const FString MatchPoolName = PoolName;
FAccelByteModelsV2MatchTicketOptionalParams Option;

Option.Latencies = ApiClient->Qos.GetCachedLatencies();
FJsonObject AttributesJsonObj{};
AttributesJsonObj.SetStringField("server_name", ServerName);
FString JsonString;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&JsonString);
TSharedPtr<FJsonObject> JsonObject = MakeShared<FJsonObject>(AttributesJsonObj);
FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);
// Convert to JSON Object Wrapper
FJsonObjectWrapper Attributes;

FAccelByteJsonConverter::JsonObjectStringToUStruct(JsonString, &Attributes);
Option.Attributes = Attributes;
Option.SessionId = SessionId;
ApiClient->MatchmakingV2.CreateMatchTicket(MatchPoolName,
AccelByte::THandler<FAccelByteModelsV2MatchmakingCreateTicketResponse>::CreateUObject(this, &AMyActor::OnCreateMatchTicketSuccess),
AccelByte::FCreateMatchmakingTicketErrorHandler::CreateUObject(this, &AMyActor::OnCreateMatchTicketFail));
}

void AMyActor::OnCreateMatchTicketSuccess(const FAccelByteModelsV2MatchmakingCreateTicketResponse& Data)
{
UE_LOG(LogTemp, Log, TEXT("Client OnCreateMatchTicketSuccess "));
}

void AMyActor::OnCreateMatchTicketFail(int32 ErrorCode, const FString& ErrorMessage, const FErrorCreateMatchmakingTicketV2& CreateTicketErrorInfo)
{
UE_LOG(LogTemp, Log, TEXT("Client OnCreateMatchTicketFail, Error code: %d\nError message:%s"), ErrorCode, *ErrorMessage);
}

ゲームセッションへの参加

ゲームセッションがすでに DS によって作成されている場合、ゲームセッションに入るもう 1 つのオプションは、ゲームセッションに直接参加することです。

void AMyActor::JoinGameSession(const FString& SessionId)
{
ApiClient->Session.JoinGameSession(
SessionId,
AccelByte::THandler<FAccelByteModelsV2GameSession>::CreateUObject(this, &AMyActor::OnJoinGameSessionSuccess),
AccelByte::FErrorHandler::CreateUObject(this, &AMyActor::OnJoinGameSessionFail));
}

void AMyActor::OnJoinGameSessionSuccess(const FAccelByteModelsV2GameSession& Result)
{
UE_LOG(LogTemp, Log, TEXT("Join Game Session Success"));
}

void AMyActor::OnJoinGameSessionFail(int32 ErrorCode, const FString& ErrorMessage)
{
UE_LOG(LogTemp, Log, TEXT("Join Game Session Fail, Error code: %d\nError message:%s"), ErrorCode, *ErrorMessage);
}

サーバーへの再接続

ゲームクライアントがサーバーから切断された場合、または以前のサービスから受信したシークレットを持っていない場合、ゲームクライアントは、REST API レスポンスを使用して関数を介して直接呼び出すことで、AGS Session からシークレットを取得できます。

void AMyActor::GetGameSessions()
{
ApiClient->SessionBrowser.GetGameSessions(
EAccelByteSessionType::dedicated,
GameMode,
AccelByte::THandler<FAccelByteModelsSessionBrowserGetResult>::CreateUObject(this, &AMyActor::OnGetGameSessionsSuccess),
AccelByte::FErrorHandler::CreateUObject(this, &AMyActor::OnGetGameSessionsFail) );
}

void AMyActor::OnGetGameSessionsSuccess(const FAccelByteModelsSessionBrowserGetResult& Result)
{
UE_LOG(LogTemp, Log, TEXT("OnGetGameSessionsSuccess "));
}

void AMyActor::OnGetGameSessionsFail(int32 ErrorCode, const FString& ErrorMessage)
{
UE_LOG(LogTemp, Log, TEXT("OnGetGameSessionsFail, Error code: %d\nError message:%s"), ErrorCode, *ErrorMessage);
}

プレイヤー検証

ゲームクライアントは DS への接続を試み、DS はプレイヤーのユーザー ID に基づいてシークレットキーを検証します。検証が完了すると、ゲームクライアントは DS に正常に接続できます。

TOTP の生成

ゲームクライアントは、セッションシークレットによって SDK に時間ベースの OTP (TOTP) をリクエストします。逆に、DS も同じシークレットを使用してゲームクライアントから送信された TOTP 値をチェックします。両側の 2 つの値を比較するには、次の関数を使用できます。

void AMyActor::GenerateTOTP(const FString& SecretKey)
{
const FString Value = FAccelByteUtilities::GenerateTOTP(SecretKey);
UE_LOG(LogTemp, Log, TEXT("GenerateTOTP value = %s"), *Value);
}
TOTP を使用したクライアントトラベル
void AMyActor::ClientTravel(const FString& TOTP)
{
TravelUrl += FString::Printf(TEXT("?totp=%s?userid=%s"), *TOTP, *ApiClient->CredentialsRef->GetUserId());
auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0);
PC->ClientTravel(TravelUrl, TRAVEL_Absolute);
}

DS の有効性チェック

void AAccelByteGameMode::PreLogin(const FString& Options, const FString& Address, const FUniqueNetIdRepl& UniqueId, FString& ErrorMessage)
{
UE_LOG(LogAccelByteDSTest, Warning, TEXT("Option: %s, Address %s"), *Options, *Address);

TArray<FString> Out;
Options.ParseIntoArray(Out, TEXT("?"), true);

FString TOTP{};
FString UserId{};
for (auto Option : Out)
{
FString Param, Value;
Option.Split(TEXT("="), &Param, &Value);
if (Param == TEXT("totp"))
{
TOTP = Value;
}
if (Param == TEXT("userid"))
{
UserId = Value;
}
}

bool Valid = FAccelByteUtilities::ValidateTOTP(Secret, TOTP, UserId);
UE_LOG(LogAccelByteDSTest, Log, TEXT("User Validity = %s"), Valid ? TEXT("Valid") : TEXT("Invalid"));

if (!Valid)
{
return;
}

// Forward to PreLogin
Super::PreLogin(Options, Address, UniqueId, ErrorMessage);
}