Верифікація даних користувачів в онлайн додатках

Всім привіт, сьогодні поговоримо про мережеву взаємодію в онлайн іграх. Та не про все, а про те, як виключити вплив некоректних даних на інших користувачів. Всі знають що сервер ніколи не повинен довіряти клієнтові, але іноді краще на практиці подивитися де і які дані обробляються на якомусь прикладі.

Хочу попередити, що стаття націлена на новачків. Людей які хотіли б написати свою першу багатокористувацьку гру. Якщо ви хоч раз займалися мережевою взаємодією в іграх, нічого корисного тут не знайдете.

Технічне відступ

І щоб не залишитися теоретичним матеріалом була написана невелика демка. Її можна запустити, подивитися даними обмінюються клієнт і сервер. На чиєму прикладі і буде розглянуто клієнт-серверне взаємодія.

Додаток використовує технологію canvas для графіки і websockets для взаємодії з сервером. Код не є предметом обговорення, тому писався швидко (основна частина близько 2-3 годин), без проектування і рефакторинга. Я не рекомендую використовувати його або його частина де б то не було.

Ви вибираєте героя, сервер вас реєструє, шукає гру. Чекає поки не ввійдуть достатню кількість гравців.



Поле схоже з тим що є в покрокових іграх аля Heroes MM. Дві команди, по чотири гравці за кожну. На початку гра будує випадкову послідовність гравців, надалі хід передається циклічно.

Кожен герой має свої характеристики атаки, захисту, дальності ходу, запасу життів.

Вибір героя здійснюється клавішами 1 — 4. Пошук ігри з обраним героєм Enter.



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

Можна було і не так вырвиглазно намалювати, але не суть.

Які дані є?
Як і в будь-якій онлайн грі, ми маємо дані про гравців. Тут для спрощення дані про грі і гравців живуть лише протягом гри, а в подальшому видаляються.

По порядку:

  • Розташування всіх юнітів в грі;
  • Парамерты героїв, обраних гравцями;
  • Приналежність до команди;
  • Черговість ходу.
Поговоримо окремо про кожен пункт.

1. Розташування юнітів. Звичайно на основі цієї інформації малюються юніти на полі, але чи можемо ми не зберігати ці дані на сервері? Ні, і ось чому. Якщо ця інформація не зберігається, то і перевіряти те як пересуваються юніти ми не можемо. А значить в незалежності від швидкості персонажа, він може хоч в інший кінець карти, хоч на місяць.

2. Від параметрів героїв, такі як рівень атаки, захисту, життів швидкості прямо залежить виживання його в агресивному середовищі. І це перше, що повинно проходити перевірку. Їх краще взагалі не пересилати, а просто дублювати.

3. Черговість ходу так само впливає на гру. Ми ж не ходимо щоб хтось ходив по п'ять разів за хід, виправдовуючись що у нього спрацювала ініціатива.

4. Приналежність

Тепер все перераховане вище на прикладі запиту на атаку (unit1 атакує unit2):

ATTACK unit1_id unit2_id

Запит в реальній грі, в залежності від механіки, може посилати додаткові дані:

{"game_key":"...","private_key":"...","action":"attack","attacked":{"x":4,"y":2},"old_position":{"x":4,"y":3}}

Де attacked це положення атакується юніта, a old_position — положення звідки буде проводитися атака.

Насправді це все, що потрібно сервера. Йому залишається провести наступні операції:

  1. Перевірити хід належить unit1
  2. Перевірити що відправлений запит від користувача, якому належить unit1
  3. може Перевірити чи unit1 атакувати unit2
Якщо всі перевірки проходять, то сервер змінює стан і відсилає цю ж операцію всім клієнтам, а ті просто приводять свій стан у актуальне. Ось так це виглядає на картинці:



Як клієнт оновлює свій стан? Запит сервера (так, саме запит):

{"new_position": {"y": 2, "x": 2}, "request": "move"}

І цього достатньо. Адже гра знає якого юніта належить хід. І знає що інформація перевірена. А значить, треба просто перемалювати активного юніта за новими координатами.

Якщо ви тільки починаєте, не гріх буде дати пораду, дублюйте взагалі всю інформацію.

Як чинити з невірними даними?
Це найскладніше питання, однозначної відповіді на нього немає. Можна, наприклад, не приймати ці запити і залишати стан гри незмінним. Можна блокувати гравця посилаючої таке запити, а перемогу присудити його супернику. Можна додатково змінювати параметри такого гравця, шлях його герой має всього одне життя (або штучно завищити складність гри). Тут ми обмежені тільки уявою.

Вихідний код

Якщо знайдеться досить користувачів можна потестить.

P. S. Шукаю роботу Python/Django розробника. З усіх питань в особисті повідомлення або на пошту.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.