2016-08-01 6 views
0

私はオンラインゲームをデザインしています。ゲーム内では、プレーヤーは一連の動きを行います。以前の動きは後の動きに影響を与えることができます。これは、移動の順序が重要であることを意味します。移動はAJAXリクエストとして実装されます。私のバックエンドはノードとexpressjsです。改ざんできない方法でhttpリクエストの順序を判断するにはどうすればよいですか?

私は非同期に動きを実装することができましたが、後の動きの後に早い動きが終了する可能性はわずかです。私は移動タスクが、要求を約束に連鎖させることによって要求を受け取った順序で完了することを確かめることができますが、別のものが前に到着する前にhttp要求が行われることを保証できますか?

私はクライアント側の移動をタイムスタンプして、その順に処理することができました。私の懸案事項は、タイムスタンプの要求をシミュレートして注文を破棄し、失ってしまったらゲームをクラッシュさせてユーザーが不正行為をする可能性があるということです。これは、いくつかの動きが間違った順序で実行されると、ゲームが中断されるためです。

もちろん、私はこのエラーを処理することができますが、複数の注文が正当なものになる可能性があるため、プレーヤーが特定の動きをするように多くの情報を持つ可能性があるため、真の順序が実行されます。たとえゲームが実際にクラッシュしなくても、真の秩序を決定することは不可能です。各リクエストにgamestate全体を含めるとしても、それは潜在的にスプーフィング可能です。

ユーザーが改ざんできないようにHTTPリクエストの順序を判断できる方法はありますか?私はこの問題に対する別の解決策を見出すことができません。

+0

私がそれを必要とするなら、私の選択はwebsocketです。 Websocketはより安全です(例:http://blog.ironwasp.org/2014/11/analysing-testing-and-fuzzing-websocket.html)。サーバー '.on( 'data' ')で定義されたクライアント要求の順序すべての要求は、クライアントとサーバーのタイムスタンプで別々の配列に格納する必要があります。サーバーは要求配列をタイムスタンプで実行する必要があります。 –

+0

github ..リンクが私のバイオにあります...私はキャンバスとsocket.ioでシンプルなゲームを作った –

+0

約束を守れば、2番目のAjaxリクエストは最初の完了まで送信されないので、注文の完全保証となります。 – jfriend00

答えて

0

あなたが解決しようとしている問題は本当に明確ではありません。 httpリクエストをたくさん作成し、送信された順番(応答が受信された順序にかかわらず)で処理するように、クライアントをコーディングするのは非常に簡単です。すべての約束ドリブンajax呼び出し(jQueryなど)とPromise.all()の単純な組み合わせは、複数のリクエストを同時に送信する場合に、これを行います。

リクエストを送信する可能性があるなど、同時に送信していない場合は、もう一度別のリクエストを送信してから(以前のレスポンスが返される前に)、さらにリクエストを送信します応答のキューを作成するだけで済みます。各Ajax呼び出しは、キュー項目に関連付けられています。応答が返ってくると、応答はキューエントリに入ります。応答が返されるたびに、応答があるキュー内の最も古いアイテムを処理し、キューの順に処理します。これにより、ランダムな送信時刻要求を行うことができますが、常に応答を順番に処理します。

この順序はすべてクライアント側で行われるため、改ざん防止はできません(クライアント側は改ざんされません)が、実際にはJavaScriptやキューのデータ構造を変更する必要があります。処理の順序を変更する物事をより不正確にするために、改ざんできないサーバーに意思決定を移さなければなりません。

単純な約束ベースのajaxキューがあります。このキューでは、必要なだけ多くのリクエストを送信でき、応答が順番に処理されることが保証されます。

var queueAjax = (function() { 
    var lastAjax = Promise.resolve(); 

    return function (url, options) { 
     // chain to the prior promise so this won't get resolved until all prior items 
     // in the queue have been fulfilled in some way 
     var priorPromise = lastAjax.catch(function() { 
      // always fulfilled 
      return; 
     }); 
     var ajaxPromise = doAjax(url, options).then(function(val) { 
      return {val: val}; 
     }, function(err) { 
      return {err: err}; 
     }); 
     lastAjax = Promise.all([ajaxPromise, priorPromise]).then(function(results) { 
      var result = results[0]; 
      // if there was an error, then throw to reject with that err 
      if (result.hasOwnProperty("err")) { 
       throw err; 
      } else { 
       return result.val; 
      } 
     }); 
     return lastAjax; 
    } 
})(); 

// sample usage 
queueAjax(someUrl, someOptions).then(function(val) { 
    // process results 
}); 

queueAjax(someUrl2, someOptions2).then(function(val) { 
    // process results 
}); 

queueAjax(someUrl3, someOptions3).then(function(val) { 
    // process results 
}); 

このキューイング・システムの機能は、並行して、AJAXリクエストを送信しますが、必ずその.then()ハンドラはリクエストが送信された順序で呼び出されます。 Promise.all()とは異なり、いつでも新しい要求をキューに追加することができ、それらはシーケンスに追加されます。

デモ:https://jsfiddle.net/jfriend00/7r2j1qme/

関連する問題