如何以无法篡改的方式确定http请求的顺序?

时间:2021-03-19 21:11:27

I am designing an online game. Within the game, a player makes a series of moves. Previous moves can effect moves can effect later moves. This means the order of moves is crucial. The moves are implemented as AJAX requests. My backend is expressjs with node.

我正在设计一款在线游戏。在游戏中,玩家进行一系列动作。以前的动作可以影响动作可以影响后期动作。这意味着移动的顺序至关重要。这些动作是作为AJAX请求实现的。我的后端是节点表达式。

I could implement moves asynchronously but there is a slight chance that earlier moves might finish after later moves. I could make sure that the move tasks are completed in the order the requests were received by chaining requests onto promises but can I guarantee that an http request made before another will arrive before another?

我可以异步地实现移动,但稍后移动之前可能会完成早期移动的可能性很小。我可以通过将请求链接到promises来确保移动任务按照接收请求的顺序完成但是我可以保证在另一个之前发出的http请求会在另一个之前到达吗?

I could timestamp the moves client side and process them in that order. My concern is that users might cheat by simulating timestamped requests, ruining the order, crashing the game if they are about to lose. This is because some moves will break the game if they are executed in the wrong order.

我可以为客户端移动时间戳并按顺序处理它们。我担心的是,用户可能会通过模拟带时间戳的请求来破坏订单,破坏游戏,如果它们即将失败则会崩溃。这是因为如果以错误的顺序执行某些动作将会破坏游戏。

Of course I can handle this error but I can't figure out the true order of moves by checking their contents because sometimes multiple orders would be legal yet players might have more information as the make certain moves so it is crucial that the true order is executed. Even though the game wouldn't actually crash it would be impossible to determine the true order. Even if I include the entire gamestate in each request it is still potentially spoofable.

当然我可以处理这个错误,但是我无法通过检查它们的内容来弄清楚移动的真实顺序,因为有时候多个订单是合法的,但是玩家可能会有更多信息作为特定的移动所以真正的顺序是至关重要的。执行。即使游戏实际上不会崩溃,也无法确定真正的顺序。即使我在每个请求中包含整个游戏状态,它仍然可能是可欺骗的。

Is there some way I can determine the order of http requests in a way that users can't tamper with? I can't see another solution to this problem.

有没有什么方法可以用户无法篡改的方式确定http请求的顺序?我看不出这个问题的另一个解决方案。

1 个解决方案

#1


0  

It's really not clear what problem you're trying to solve. It is very simple to code a client to make a bunch of http requests and to then process them in the order they were sent (regardless of the order the responses were received). A simple combination of any promise-driven ajax call (such as jQuery) and Promise.all() will do that for you if you are sending multiple requests at the same time.

目前还不清楚你要解决的问题是什么。编写客户端以编写一堆http请求然后按发送顺序处理它们(无论收到响应的顺序如何)都非常简单。如果您同时发送多个请求,任何promise驱动的ajax调用(例如jQuery)和Promise.all()的简单组合都将为您完成。

If you are not sending them at the same time, such that you might send a request, a little later send another request (but before previous response is back), then send some more requests, etc..., then you can just create a queue for responses. Each Ajax call is tied to a queue entry. When the response comes back the response goes into the queue entry. Each time you get a response, you process the oldest items in the queue that you have responses for and you process them in the order of the queue. This allows you to do random send time requests, but always process responses in order.

如果您不是同时发送它们,以便您可以发送请求,稍后发送另一个请求(但在之前的响应返回之前),然后发送更多请求等等,然后您可以创建响应队列。每个Ajax调用都与一个队列条目相关联。当响应返回时,响应进入队列条目。每次获得响应时,都会处理队列中您有响应的最旧项目,并按队列顺序处理它们。这允许您执行随机发送时间请求,但始终按顺序处理响应。

Since all of this ordering is done client-side, it is not tamperproof (nothing done client-side is tamperproof), but it would require actual modification of the Javascript or the queue data structure, not just modifying a response in order to change the order of processing. To makes things more tamperproof, you have to move more decision making to the server where it can't be tampered with.

由于所有这些排序都是在客户端完成的,因此它不是防篡改的(客户端没有做任何防篡改),但它需要实际修改Javascript或队列数据结构,而不仅仅是修改响应以便更改处理顺序。为了使事情更加防篡改,您必须将更多决策制定移动到无法篡改的服务器上。

Here's a simple promise-based ajax queue that lets you send as many requests as you want and guarantees that the responses will be processed in order.

这是一个简单的基于promise的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
});

This queuing system function sends the ajax requests in parallel, but makes sure their .then() handlers are called in the order the requests were sent. Unlike Promise.all(), you can add new requests to the queue at any time and they will just be added to the sequence.

此排队系统函数并行发送ajax请求,但确保按发送请求的顺序调用其.then()处理程序。与Promise.all()不同,您可以随时向队列添加新请求,它们只会添加到序列中。

Here's a working demo: https://jsfiddle.net/jfriend00/7r2j1qme/

这是一个有效的演示:https://jsfiddle.net/jfriend00/7r2j1qme/

#1


0  

It's really not clear what problem you're trying to solve. It is very simple to code a client to make a bunch of http requests and to then process them in the order they were sent (regardless of the order the responses were received). A simple combination of any promise-driven ajax call (such as jQuery) and Promise.all() will do that for you if you are sending multiple requests at the same time.

目前还不清楚你要解决的问题是什么。编写客户端以编写一堆http请求然后按发送顺序处理它们(无论收到响应的顺序如何)都非常简单。如果您同时发送多个请求,任何promise驱动的ajax调用(例如jQuery)和Promise.all()的简单组合都将为您完成。

If you are not sending them at the same time, such that you might send a request, a little later send another request (but before previous response is back), then send some more requests, etc..., then you can just create a queue for responses. Each Ajax call is tied to a queue entry. When the response comes back the response goes into the queue entry. Each time you get a response, you process the oldest items in the queue that you have responses for and you process them in the order of the queue. This allows you to do random send time requests, but always process responses in order.

如果您不是同时发送它们,以便您可以发送请求,稍后发送另一个请求(但在之前的响应返回之前),然后发送更多请求等等,然后您可以创建响应队列。每个Ajax调用都与一个队列条目相关联。当响应返回时,响应进入队列条目。每次获得响应时,都会处理队列中您有响应的最旧项目,并按队列顺序处理它们。这允许您执行随机发送时间请求,但始终按顺序处理响应。

Since all of this ordering is done client-side, it is not tamperproof (nothing done client-side is tamperproof), but it would require actual modification of the Javascript or the queue data structure, not just modifying a response in order to change the order of processing. To makes things more tamperproof, you have to move more decision making to the server where it can't be tampered with.

由于所有这些排序都是在客户端完成的,因此它不是防篡改的(客户端没有做任何防篡改),但它需要实际修改Javascript或队列数据结构,而不仅仅是修改响应以便更改处理顺序。为了使事情更加防篡改,您必须将更多决策制定移动到无法篡改的服务器上。

Here's a simple promise-based ajax queue that lets you send as many requests as you want and guarantees that the responses will be processed in order.

这是一个简单的基于promise的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
});

This queuing system function sends the ajax requests in parallel, but makes sure their .then() handlers are called in the order the requests were sent. Unlike Promise.all(), you can add new requests to the queue at any time and they will just be added to the sequence.

此排队系统函数并行发送ajax请求,但确保按发送请求的顺序调用其.then()处理程序。与Promise.all()不同,您可以随时向队列添加新请求,它们只会添加到序列中。

Here's a working demo: https://jsfiddle.net/jfriend00/7r2j1qme/

这是一个有效的演示:https://jsfiddle.net/jfriend00/7r2j1qme/