🇬🇧 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.
Як увімкнути¶
- Відкрийте цю сторінку в Project Settings.
- Увімкніть b Use Editor Credentials.
- Заповніть Credentials так само, як на основній сторінці — той самий вибір
Auth Typeі ті самі поля (Basic/Token/JWT).
Готово. Тепер:
- Connect To Server на підсистемі (і з Blueprint, і з C++) використовує саме ці дані;
- кнопка Test Connection — теж;
- кнопка Test JetStream — теж.
Кожна з двох кнопок додає до спливаючого сповіщення позначку (Editor-only credentials),
щоб було видно, які саме дані щойно спрацювали — основні чи редакторський оверрайд.
Чому це безпечно¶
Значення зберігаються в Saved/Config/<Platform>/EditorPerProjectUserSettings.ini —
файлі, який:
- лежить у теці
Saved/, яку стандартний.gitignoreUnreal-проєкту виключає із системи контролю версій за замовчуванням — секрет не потрапить у 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