質問: 自分の作ったブラウザゲームのスコア(JSの変数に格納)をXMLHttpRequestでPHPに送信し、PHPでランキングに反映させることをしています。 しかし、JSの変数はChromeなどのデベロッパーツールで中身を書き換えられてしまい、チートのようなことが可能になってしまいます。 また、外部サイトなどからPOSTで送信しても、ランキングが更新できてしまう致命的なバグもあります。 なので、自分が求めるものとしては以下のものです。 ・スコアの更新はそのゲームのサイトからしか行えないようにする。つまり外部サイトからPOST送信しても処理されなくする。 ・JSの変数の書き換え対策 自分なりに考えたのが、サイト訪問時に鍵のようなものを発行し、それがなければランキング登録ができないというものです。(書き換え対策できてない) 何かチートされないための工夫や解決策がご教授ください。
回答: 質問文で出てきた2つの方針はどちらも対策としては微妙です。 まだまだHTTPの仕様周りの理解が相当不足してるんじゃないかと思います。 もう少しHTTPやWebサーバ、ブラウザの仕様に関して勉強した方が良いでしょう。 > > ・スコアの更新はそのゲームのサイトからしか行えないようにする。つまり外部サイトからPOST送信しても処理されなくする。 > > > どうやって? 例えば「そのゲームのサイト」というのはHTTPリクエストのヘッダー内のRefererの事を指しているのでしょうか? もしそうならRefererは「自己申告」ですので確認しても無駄です。 こういうスコア申請チートをしようとしてる輩が知らない訳無いでしょというレベルであり、 一度デベロッパーツール等で送信しているHTTPリクエストを確認して模倣するだけの単純作業で突破されます。 > > ・JSの変数の書き換え対策 > > > これもどうやって? JavaScriptというのはブラウザ作ってるベンダーが各自エンジンを作っており、 WebサーバというのはJSファイルを送信して「読み込んで実行して下さいお願いします」ってお願いしている側です。 なのでフリーで配布されているChroniumを改造して自作ブラウザを作ったり、 間に改ざん用のスクリプトを挟み込んで実行するようなケースを考えると、 そもそもJavaScriptが意図通りに動いてくれる保証なんて何処にもありません。 という訳で、ローカルでゲームをさせて、 その結果だけ送って下さいという方式でハイスコア計算を行う仕組みはチートに対して無力です。 対策も何もありません。 te2jiさんが出してたURL内のハッシュを送れという対策も、 ハッシュを作るアルゴリズムがJS内にあるのにどうすんねんという感じですね。 なので、結局大抵のソシャゲは逐一サーバーへ接続してお伺いを立てるわけですね。 サーバー側に乱数含めて一切の権限をもたせることで、クライアントには表示しか任せない。 流行れば負荷は莫大なものになるので、ガチャでSSRをばらまくことでAWSのインスタンス代金を補填すると...... > > 何かチートされないための工夫や解決策がご教授ください。 > > > まぁ、私が思いつくのは棋譜の提出ですね。 将棋には棋譜があるように、ゲームをプレイすればその痕跡が残ります。 これを利用した手法が格ゲーのキーディスプレイ。 現行の格ゲーは両方のプレイヤーの操作内容が乗りますので、それの提出を迫れば改ざんはほぼ不可能になります。 例えうまく改ざんしたとしても、旧に相手プレイヤーが変な行動をし始めれば、後から検証してすぐに分かります。 つまり、格ゲーはキーディスプレイを読み込ませてゲームを再現させれば良いのです。 しかし、一般的なゲームには乱数が加わるものが多いですね。 一見チート対策は不可能なように思えますが、それにも抜け道があります。 例えばSFCのいただきストリートでは、SFCに予めどの順番でどの乱数が出るかという乱数表が用意されており、 ゲーム開始時にどの乱数でゲーム開始したか、要所要所でどの選択をしたのかという情報を元にして改ざん対策をしています。 サイコロを振って他のプレイヤーのお店に入る事が決定した瞬間にリセットボタンを押し、 ゲームをロードしてサイコロを振り直す不正を行ったとしても、出る目は同じなのでセーブ・ロードで簡単に未来は変えられません。 これを見習って、開始乱数表のアドレスとキャラクターの初期状態、操作内容を提出し、 サーバー内で実際にゲームを再生して妥当なら受理するという作りにするのが間違いないでしょう。 そのうち乱数固定チートの最適解棋譜提出みたいな事はされそうですが、時間は稼げるし、SFC版シムシティのマップ番号別タイムアタックみたいな遊び方は出来ると思います。