Upgrade to Pro — share decks privately, control downloads, hide ads and more …

フルスタックGoでスコア改ざんを防いだ話

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for ponyo877 ponyo877
February 18, 2026

 フルスタックGoでスコア改ざんを防いだ話

Avatar for ponyo877

ponyo877

February 18, 2026
Tweet

More Decks by ponyo877

Other Decks in Technology

Transcript

  1. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 2 / 17

    自己紹介 ぽにょ / ponyo877 • GoでSaaSを作るエンジニア • X:@ponyo877 • GitHub:@ponyo877 • 好きなもの:映画館のポップコーン • 趣味:個人開発
  2. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 3 / 17

    今回のテーマ・話すこと 「Ebitengine」で作った「オンラインランキング付きのゲー ムのスコアの改ざん防止 」をする時に「クライアントとサー バも同じGoのコードを共有 」した多分レアな事例
  3. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 4 / 17

    作ったもの ”Ebitengineでオンラインランキング付きのゲームを作った際に...” Ebitengineとは?
  4. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 6 / 17

    Ebitengine ゲーム状態の更新のUpdateと画面描画のDrawを実装すればゲームが作れる
  5. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 7 / 17

    作ったもの Ebitengineのサンプルゲーム Flappy Gopherにオンラインランキングを付けた
  6. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 8 / 17

    課題:ブラウザゲームのスコア改ざん { ”score”: 10 999999 } > curl -X POST -d {“score”: 999999} https://api... 開発者ツールなどでAPIは丸見え、書き換えて送信すれば簡単に改ざんできる
  7. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 9 / 17

    解決策:スコアではなく操作履歴を送る { “score”: 999999 } { “jumpHistory”: [ 736, 1440, 2816 ] } POST /score POST /history
  8. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 10 / 17

    チート対策フロー図 | 土管の位置決め 土管シード 生成 ゲームスタート依 頼 土管シード 土管シードで発生させた乱数を使っ て土管の隙間の位置を決める 土管の隙間生成乱数のseedをサーバで発生させ、サーバで管理(元はseedなし)
  9. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 11 / 17

    チート対策フロー図 | ジャンプ履歴の蓄積と送信 ゲームスタート! ジャンプ x n回 ジャンプのタイミングをブラウザに蓄積 jumpHistory.append(X) >< Hit x=10 x=22 x=49 x=41 ジャンプ履歴 [10, 22, 41, 49] 60FPSで動いているタイマーのどの時点でジャンプしたかを記録し最後に送信
  10. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 12 / 17

    チート対策フロー図 | サーバでシミュレーション ゲーム終了 スコア保存完了 >< Hit x=10 x=22 x=49 x=41 シミュレーション → スコア計算 ジャンプ履歴 [10, 22, 41, 49] ※ ここでゲーム開始・終了時間から プレイ時間を算出→検証もやっている クライアントと同じゲームロジックを早回しして再現、サーバ側でスコア計算
  11. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 13 / 17

    クライアント /サーバーでロジック共有 クライアントのゲームループ サーバでの検証 ゲームの状態 衝突計算 Browser WebAssembly Ebitengine Cloudflare Workers syumai/workers D1 common package
  12. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 14 / 17

    commonパッケージで共有するもの ゲームの状態を表す構造体 • キャラクタの現在座標と速度 • 土管の隙間の配置 ゲームの状態から計算する以下のメソッド 衝突判定するメソッド スコア判定するメソッド
  13. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 15 / 17

    サーバーサイドシミュレーション(コード) ゲーム開始時に出した土管シードから生成した乱 数で土管の隙間の位置を計算 LOOP: 下向きの速度から次のy座標を計算 重力加速度による下向きの速度を加える IF ジャンプ: 上向きの速度を加える IF 土管に衝突: 潜った土管の数がスコアになる RERURN
  14. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 16 / 17

    追加の防止策 | プレイ時間検証 早すぎる ☺適切なプレイ時間☺ 遅すぎる 時間かけて攻略することの防止 ゲーム速度を落としの防止 60FPSでの最速の終了時間 30FPSでの最遅の終了時間 防止策の強化としてプレイ時間の検証も併せて実施 開始・終了時にクライアントからリクエストを遅らせサーバ側でプレイ時間を計算し適切 なプレイ時間か検証 time
  15. フルスタックGoでスコア改ざんを防いだ話 | ponyo877 2026-02-18 | golang.tokyo #43 17 / 17

    まとめ ブラウザゲームのスコア改ざん問題を以下の解決策で防いだ • スコアではなくjumpHistoryを送信 • サーバー側でシミュレーション クライアントとサーバでのGoのコード共有というレア実装で実現できた 理論的な詳細はZennにまとめの記事があり ブラウザゲームでハイスコアに挑 戦!https://flappy-ranking.pages.dev