如何检查AJAX请求的真实性 [英] How to Check Authenticity of an AJAX Request

查看:206
本文介绍了如何检查AJAX请求的真实性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设计一个网站,用户可以尽快解决谜题。 JavaScript用于计算每个拼图,并且当拼图完成时,通过AJAX将毫秒数发送到服务器。我如何确保服务器接收的时间没有被用户伪造?



我不认为基于会话的真实性令牌(用于表单的类型在Rails中)是足够的,因为我需要验证一个值的,而不仅仅是请求的合法性。



有没有办法密码地签署请求?我不能想到任何不能被黑客重复的东西。任何JavaScript,由于其暴露的客户端性质受到篡改?我要使用像Flash这样编译的东西吗? (Yikes。)还是有办法隐藏密钥?还有别的我还没有想到的?



更新:为了澄清,我不想惩罚网络连接速度慢的人(网络速度应该被认为是不一致的) ),所以时间需要是100%客户端(只有当我们知道用户可以看到谜题时,定时器才会启动)。此外,有钱涉及,所以没有数量的信任用户是可以接受的。

解决方案

这种方法显然是假设,不可战胜所有计算都在客户端进行,服务器会进行一些后台检查,以确定请求是否可能被伪造。像任何其他基于客户端的方法一样,这并不是确定性的,但是对于一个说谎的客户端来说这是非常困难的。



主要的假设是长时间的HTTP连接要快得多用于传输数据,在某些情况下,根据应用程序上下文甚至可以忽略不计。它在大多数在线交易系统中使用,因为股票价格可能在一秒钟内变化多次,这是将当前价格传输给用户的最快方式。您可以在这里阅读有关 HTTP Streaming或Comet 的更多信息。



首先创建一个全双工 ajax连接客户端和服务器。服务器有专线与客户端通话,客户端可以明显地与服务器通话。服务器将这个谜题和其他消息发送到该专用线上的客户端。客户端应该确认每个消息的接收与其本地时间戳一起。



在服务器上生成随机令牌(可能只是不同的整数)之后拼图已发送,记录生成每个令牌的时间,并将其传递给客户端。客户端看到该消息,并且应该立即将该令牌转发回来以及当地的接收时间。为了使客户端不可预测,请以随机间隔生成这些服务器令牌,例如介于 1 n ms之间。 / p>

客户端将发送到服务器的消息有三种:

  PUZZLE_RECEIVED 
TOKEN_RECEIVED
PUZZLE_COMPLETED

和两种类型的消息服务器发送给客户端:

  PUZZLE_SENT 
TOKEN_SENT

有可能在从客户端发送到服务器的消息中有很多时间变化,但是在另一个方向上更小(和这是一个非常公平的假设,嘿,我们必须从某个地方开始。)



现在当服务器收到发送的消息的收据时,记录下载的客户端时间信息。由于令牌还在此消息中被中继,我们可以将其与服务器上的相应令牌进行匹配。在拼图结束时,客户端会向服务器发送一个具有本地时间的 PUZZLE_COMPLETED 消息。完成拼图的时间将是:

  PUZZLE_COMPLETED.time  -  PUZZLE_RECEIVED.time 

然后通过计算每封邮件与收到的时间的时差进行双重检查。

  PUZZLE_RECEIVED.time  -  PUZZLE_SENT.time 
TOKEN_RECEIVED.time - TOKEN_SENT.time

这些时间的高度差异意味着响应可能已被伪造。除了简单的方差之外,还有很多关于这些数据的统计分析可以寻找奇怪的模式。


I am designing a web site in which users solve puzzles as quickly as they can. JavaScript is used to time each puzzle, and the number of milliseconds is sent to the server via AJAX when the puzzle is completed. How can I ensure that the time received by the server was not forged by the user?

I don't think a session-based authenticity token (the kind used for forms in Rails) is sufficient because I need to authenticate the source of a value, not just the legitimacy of the request.

Is there a way to cryptographically sign the request? I can't think of anything that couldn't be duplicated by a hacker. Is any JavaScript, by its exposed, client-side nature, subject to tampering? Am I going to have to use something that gets compiled, like Flash? (Yikes.) Or is there some way to hide a secret key? Or something else I haven't thought of?

Update: To clarify, I don't want to penalize people with slow network connections (and network speed should be considered inconsistent), so the timing needs to be 100% client-side (the timer starts only when we know the user can see the puzzle). Also, there is money involved so no amount of "trusting the user" is acceptable.

解决方案

This approach obviously makes assumptions and is not invincible. All calculations are done on the client, and the server does some background checks to find out if the request could have been forged. Like any other client-based approach, this is not deterministic but makes it very hard for a lying client.

The main assumption is that long-lived HTTP connections are much faster for transmitting data, even negligible in some cases depending on the application context. It is used in most online trading systems as stock prices can change multiple times within a second, and this is the fastest way to transmit current price to users. You can read up more about HTTP Streaming or Comet here.

Start by creating a full-duplex ajax connection between the client and server. The server has a dedicated line to talk to the client, and the client can obviously talk to the server. The server sends the puzzle, and other messages to the client on this dedicated line. The client is supposed to confirm the receipt of each message to the server along with its local timestamp.

On the server generate random tokens (could be just distinct integers) after the puzzle has been sent, record the time when each token was generated, and pass it over to the client. The client sees the message, and is supposed to immediately relay this token back along with it's local time of receipt. To make it unpredictable for the client, generate these server tokens at random intervals, say between 1 and n ms.

There would be three types of messages that the client sends to the server:

PUZZLE_RECEIVED
TOKEN_RECEIVED
PUZZLE_COMPLETED

And two types of messages that the server sends to the client:

PUZZLE_SENT
TOKEN_SENT

There could be a lot of time variation in the messages send from the client to the server, but much lesser in the other direction (and that's a very fair assumption, hey - we have to start somewhere).

Now when the server receives a receipt to a message it sent, record the client time contained in that message. Since the token was also relayed back in this message, we can match it with the corresponding token on the server. At the end of the puzzle, the client sends a PUZZLE_COMPLETED message with local time to the server. The time to complete the puzzle would be:

PUZZLE_COMPLETED.time - PUZZLE_RECEIVED.time

Then double check by calculating the time difference in each message's sent vs received times.

PUZZLE_RECEIVED.time - PUZZLE_SENT.time
TOKEN_RECEIVED.time - TOKEN_SENT.time

A high variance in these times implies that the response could have been forged. Besides simple variance, there is lots of statistical analysis you can do on this data to look for odd patterns.

这篇关于如何检查AJAX请求的真实性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆