Skip to content

🇬🇧 English | 🇺🇦 Українська

← До змісту

4. Облікові дані: як не зберігати секрети в клієнті

У 3. Налаштуваннях показано де технічно вписати облікові дані. Цей розділ — про інше питання: де їм узагалі не місце, і що робити замість цього. Прочитайте його, перш ніж вписувати реальний пароль чи токен у будь-яке поле плагіна.


Чому це взагалі важливо

Будь-яка гра — це програма, яка виконується на пристрої гравця. Усе, що потрапляє в зібрану гру — код, ассети, конфігураційні файли, — фізично лежить на диску гравця й рано чи пізно може бути прочитане: інструментами розпакування .pak, дебагером, чи просто текстовим редактором, якщо конфіг не запакований. Шифрування ассетів тут не рятує: щоб підключитися до сервера, сам клієнт мусить мати секрет у відкритому вигляді в оперативній пам'яті в момент підключення — а це означає, що рано чи пізно він доступний тому, хто повністю контролює власний пристрій (тобто будь-якому гравцеві).

Практичне правило: якщо секрет фізично потрапив у зібрану гру — вважайте його оприлюдненим. Питання не «чи можуть його знайти», а «коли». Тому справжній захист — не ховати секрет краще, а взагалі не класти в те, що йде гравцю.


Три місця для облікових даних — і коли яке доречне

Місце Потрапляє у зібрану гру? Коли доречне
Project Settings → Credentials (3. Налаштування) Так, у відкритому вигляді, у DefaultGame.ini Локальна розробка; сервер узагалі без чутливих даних; невисока значущість витоку (наприклад, спільний тестовий токен на закритому стенді)
Editor Only credentials (нижче) Ні — фізично відсутнє в білді Тестування в редакторі (Play In Editor, кнопки Test Connection/Test JetStream) з реальними, чутливими обліковими даними — без ризику випадково закомітити їх у Project Settings
Отримання під час виконання (нижче) Ні — секрету немає в жодному файлі проєкту взагалі Продакшн: гра гравця чи виділений сервер повинні підключатися до реального сервера з реальними правами доступу

Перші два розв'язують проблему лише для розробника, що працює в редакторі. Якщо ваша гра (не редактор) підключається до продакшн-сервера — вам потрібен третій варіант, розібраний нижче докладно.


Editor Only credentials: для тестування в редакторі

Editor Preferences → Plugins → NATS Messaging Client (Editor Only)

Окрема сторінка налаштувань поруч з основною — саме для того, щоб тестувати в редакторі з реальними обліковими даними, жодного разу не вписавши їх у поле, яке зберігається в DefaultGame.ini.

Як увімкнути

  1. Відкрийте цю сторінку в Project Settings.
  2. Увімкніть b Use Editor Credentials.
  3. Заповніть Credentials так само, як на основній сторінці — той самий вибір Auth Type і ті самі поля (Basic/Token/JWT).

Готово. Тепер:

  • Connect To Server на підсистемі (і з Blueprint, і з C++) використовує саме ці дані;
  • кнопка Test Connection — теж;
  • кнопка Test JetStream — теж.

Кожна з двох кнопок додає до спливаючого сповіщення позначку (Editor-only credentials), щоб було видно, які саме дані щойно спрацювали — основні чи редакторський оверрайд.

Чому це безпечно

Значення зберігаються в Saved/Config/<Platform>/EditorPerProjectUserSettings.ini — файлі, який:

  • лежить у теці Saved/, яку стандартний .gitignore Unreal-проєкту виключає із системи контролю версій за замовчуванням — секрет не потрапить у git, навіть якщо ви забудете про нього;
  • належить конкретно вашій машині й вашому користувачеві операційної системи — не синхронізується разом із проєктом на інший комп'ютер;
  • фізично не входить у зібрану гру. Сам клас цих налаштувань компілюється лише для редакторських збірок — у Development/Shipping-конфігурації гри ці дані не просто не читаються, а відсутні в бінарнику як такому.

Важливе обмеження

Editor Only credentials впливають лише на те, що відбувається в редакторі. Це:

  • Connect To Server на підсистемі, коли ви граєте в PIE;
  • дві кнопки перевірки.

Це не впливає на:

  • NATS Client Component — у нього власне поле Nats Credentials на кожному акторі, редакторський оверрайд його не підмінює;
  • зібрану гру, яку запустив гравець, — там цього класу налаштувань узагалі не існує (як щойно пояснено вище), тож підмінювати там просто нічому.

Іншими словами: Editor Only credentials розв'язують проблему тестування, а не проблему продакшну. Гра гравця й далі підключатиметься тими обліковими даними, які вписано на основній сторінці Project Settings, — тобто якщо там нічого чутливого не лишили, гра підключиться з Auth Type = None чи з тим, що ви передасте кодом. Саме для «підключити гравця з реальними правами» призначений наступний розділ.


Runtime: отримання облікових даних ззовні

Це — спосіб, яким продакшн-гра чи виділений сервер отримують реальні, чутливі облікові дані, не зберігаючи їх у жодному файлі проєкту взагалі. Секрет живе лише в оперативній пам'яті, на час одного сеансу, і потрапляє туди з джерела, яке ви контролюєте самі — не з .ini файлу, що йде разом зі збіркою.

Механіка на боці плагіна одна й та сама, незалежно від джерела: зібрати FNatsCredentials (чи Blueprint-структуру Make Nats Credentials) і передати Connect With Credentials — детально розібрано в 3. Налаштування → Де задати облікові дані. Різниця — лише в тому, звідки беруться значення для цієї структури. Нижче — конкретні, типові джерела.

Сценарій 1: гра гравця отримує токен від вашого бекенда після логіну

Найпоширеніший випадок. У гравця вже є свій обліковий запис у вашій системі (не в NATS) — логін, реєстрація, авторизація через платформу (Steam, PlayStation Network тощо). Ваш бекенд-сервер, переконавшись, хто цей гравець, видає йому короткостроковий NATS-токен (чи JWT) саме для цього сеансу — і от його вже передають у плагін.

[Гравець увійшов у гру — Login успішний]
   │
   └─► [Ваш HTTP-запит до бекенда: "видай мені NATS-токен для цього сеансу"]
          │
          └─► [Відповідь бекенда містить токен]
                 │
                 └─► Make Nats Credentials
                        Auth Type : Token
                        Token     : (з відповіді бекенда)
                        │
                        └─► Get Game Instance Subsystem (Nats Client Subsystem)
                               │
                               └─► Connect With Credentials
                                      Server URL     : "nats.mygame.com"
                                      Port           : 4222
                                      In Credentials : (зверху)
void AMyPlayerController::OnBackendLoginSuccess(const FString& NatsToken)
{
    FNatsCredentials Credentials;
    Credentials.AuthType = ENatsAuthType::Token;
    Credentials.Token = NatsToken;

    UNatsClientSubsystem* Nats = GetGameInstance()->GetSubsystem<UNatsClientSubsystem>();
    Nats->ConnectWithCredentials(TEXT("nats.mygame.com"), 4222, Credentials);
}

Сам HTTP-запит до бекенда плагін не реалізує — це звичайний виклик вашого API, тим механізмом, яким ваш проєкт уже спілкується з бекендом (модуль HTTP Unreal, чи будь-який інший інструмент, яким ви користуєтеся для власного backend-протоколу).

Чому це безпечно. Токен ніколи не записується на диск гравця в жодному конфігураційному файлі — він існує лише в оперативній пам'яті поточного сеансу гри. Якщо гравець спробує підглянути «пароль до NATS» у файлах гри — там просто нічого немає. Токен до того ж можна зробити короткостроковим на боці бекенда (наприклад, дійсним годину) — навіть якщо його й перехопили з трафіка чи з пам'яті процесу, шкода обмежена в часі.

Сценарій 2: виділений сервер отримує секрет при запуску

Для dedicated server (де немає гравця й немає етапу «логін») типове джерело — саме середовище запуску, а не бекенд-запит: аргумент командного рядка чи змінна середовища, які встановлює той, хто розгортає сервер (ви самі, ваш DevOps, оркестратор на кшталт Kubernetes чи Docker Compose із секретами).

void AMyGameMode::BeginPlay()
{
    Super::BeginPlay();

    // З аргументу командного рядка: -NatsToken=секрет
    FString Token;
    if (!FParse::Value(FCommandLine::Get(), TEXT("NatsToken="), Token))
    {
        // Або зі змінної середовища, якщо командний рядок не задано
        Token = FPlatformMisc::GetEnvironmentVariable(TEXT("NATS_TOKEN"));
    }

    if (Token.IsEmpty())
    {
        UE_LOG(LogTemp, Error, TEXT("NATS-токен не задано: сервер запущено без -NatsToken і без NATS_TOKEN"));
        return;
    }

    FNatsCredentials Credentials;
    Credentials.AuthType = ENatsAuthType::Token;
    Credentials.Token = Token;

    UNatsClientSubsystem* Nats = GetGameInstance()->GetSubsystem<UNatsClientSubsystem>();
    Nats->ConnectWithCredentials(TEXT("nats.mygame.com"), 4222, Credentials);
}

Запуск сервера тоді виглядає так:

./MyGameServer -NatsToken=реальний_секрет_сервера
# або
NATS_TOKEN=реальний_секрет_сервера ./MyGameServer

Читання аргументів командного рядка й змінних середовища (FParse::Value, FPlatformMisc::GetEnvironmentVariable) — стандартні можливості самого Unreal, доступні лише з C++. Готової Blueprint-ноди для цього в базовому рушії немає — якщо потрібен саме Blueprint, оберніть виклик у свою просту BlueprintCallable-функцію на боці проєкту.

Чому це безпечно. Секрет не лежить у жодному файлі гри чи проєкту — він живе в оточенні процесу (змінна середовища чи аргумент запуску), яке контролює той, хто розгортає сервер, і яке типово ніколи не потрапляє в систему контролю версій разом із кодом гри.

Інші джерела — коротко

  • Сервер, налаштований на видачу облікових даних сам (auth callout чи подібний механізм) — плагін підтримує передавання JWT-токена як є, без підпису NKey; детальніше й з застереженням — 3. Налаштування → Облікові дані.
  • Системне сховище секретів (Keychain, Windows Credential Manager тощо). Плагін не надає готової інтеграції — якщо потрібен саме такий рівень захисту, читайте секрет звідти власним кодом (поза плагіном) і так само передавайте результат у Connect With Credentials. Сам плагін не диктує, звідки саме взявся рядок токена чи пароля — лише приймає готовий результат.

Підсумок: що вибрати

Чи це продакшн-сервер, до якого підключиться справжня гра чи справжній гравець?
   │
   ├─ Ні, це лише мій локальний тест / сервер без чутливих даних
   │      → Project Settings, основна сторінка. Просто і достатньо.
   │
   └─ Так
          │
          ├─ Я зараз тестую цей продакшн-сервер із редактора
          │      → Editor Only credentials (цей розділ, вище)
          │
          └─ Так підключатиметься сама гра гравця чи виділений сервер
                 → Runtime-отримання (цей розділ, «Сценарій 1» чи «Сценарій 2» вище)
                    + Connect With Credentials

Далі: 5. Основний обмін повідомленнями