2

我之前问过一个类似的问题,答案很简单:

如果 JavaScript 可以做到,那么任何客户端都可以做到。

但我仍然想找到一种方法来限制对 JavaScript 的 AJAX 调用。

原因是 :

我正在构建一个 Web 应用程序,当用户单击图像时,标记如下:

<img src='src.jpg' data-id='42'/>

JavaScript 像这样调用 PHP 页面:

$.ajax("action.php?action=click&id=42");

然后 action.php 在数据库中插入行。

但我担心一些用户可以通过调用必要的 url 来自动“点击”所有 id 等条目,因为它们在源代码中是可见的。

我怎样才能防止这样的事情,并确保它只在点击时起作用,而不是通过从浏览器选项卡调用 url?

ps

我认为一个可能的解决方案是使用加密,例如在用户访问时生成一个密钥,并使用该密钥或 hash/md5sum/其他任何内容调用操作页面。但我认为它可以在不将其转化为安全问题的情况下完成。我对吗 ?此外,我不确定这种方法是否是一种解决方案,因为我对这种安全性或其实现一无所知。

4

5 回答 5

2

我不确定是否有 100% 安全的答案。将服务器生成的令牌插入隐藏的表单元素和反自动化技术(如限制特定时间段内的请求数量)的组合是我能想到的最好的方法。

[编辑] 实际上一个好的解决方案是使用 CAPTCHAS

于 2013-08-07T13:27:49.450 回答
2

您的问题并不是真正的“我如何区分 AJAX 和非 AJAX?” 它是“我如何阻止有人通过重复点击和选票填充来夸大分数?”

在回答您提出的问题时,您引用的答案基本上是正确的。没有可靠的方法来确定请求是由 AJAX、特定浏览器、CURL 会话还是由在 telnet 会话中输入原始 HTTP 命令的人发出的。我们可能会看到浏览器、脚本或应用程序,但 PHP 看到的只是:

GET /resource.html HTTP/1.1
host:www.example.com

如果出于方便的原因想知道请求是否为 AJAX,一些 javascript 库(例如 jQuery)会为您可以查找的 AJAX 请求添加额外的 HTTP 标头,或者您可以手动添加标头或在有效负载中包含字段,例如作为 AJAX=1。然后,您可以检查这些服务器端并采取您认为应该为 AJAX 请求执行的任何操作。

当然,没有什么能阻止我使用 CURL 发出相同的请求,并设置正确的标头以使服务器认为它是 AJAX 请求。因此,您应该只在对请求是否为 AJAX 感兴趣时才使用此类技巧,以便您可以正确格式化响应(如果不是 AJAX,则发送 HTML 页面,如果是则发送 JSON)。您的应用程序的安全性不能依赖于这些技巧,如果您的应用程序设计出于安全或可靠性原因需要能够区分 AJAX 和非 AJAX,那么您需要重新考虑应用程序的设计。

为了回答您实际想要实现的目标,有几种方法。但是,没有一个是完全可靠的。第一种方法是在第一次点击时在用户的机器上存放一个 cookie,如果 cookie 在任何后续请求中,则忽略来自该用户代理的任何后续请求。这是一种相当简单、轻量级的方法,但也很容易通过简单地删除 cookie 或一开始就拒绝接受它而失败。

或者,当用户发出 AJAX 请求时,您可以记录有关请求用户代理的一些信息以及提交点击的事实。例如,您可以存储客户端 IP 和用户代理字符串的散列(使用比 MD5 更强的内容存储!),以及单击的时间戳。如果您看到很多相同的哈希值以及紧密分组的时间戳,则可能存在滥用行为。同样,这个技巧不是 100% 可靠的,因为用户代理可以看到他们想要的任何字符串作为他们的用户代理字符串。

于 2013-08-07T13:44:47.633 回答
0

使用 post 方法而不是 get。阅读此处的文档http://api.jquery.com/jQuery.post/ 以了解如何在 jquery 中使用 post 方法

于 2013-08-07T13:19:08.590 回答
0

例如,您可以检查请求是否真的使用 AJAX 完成,而不仅仅是调用 URL。

if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
    // Yay, it is ajax!
} else {
    // no AJAX, man..
}
于 2013-08-07T13:20:27.770 回答
0

此解决方案可能需要更多反思,但可能会奏效

您可以使用 Slicedpan 的回答中所述的令牌。在为您的页面提供服务时,您将为每个图像生成 uuid 并将它们存储在会话/数据库中。

然后将您的html作为

<img src='src.jpg' data-id='42' data-uuid='uuidgenerated'/>

您的 ajax 请求将变为

$.ajax("action.php?action=click&uuid=uuidgenerated");

然后在 php 端,检查内存/数据库中的 uuid,并允许或不允许事务。(您还可以检查在 ajax 上发送的自定义标头,如其他响应中所述)

您还需要清除 uuid、令牌生存期、窗口卸载、会话过期...

此方法不会让您知道请求是否来自 xhr,但您可以限制他们的数量。

于 2013-08-07T13:33:09.910 回答