如何防止PHP中的ajax-spam?

时间:2011-03-04 16:53:45

标签: php ajax spam-prevention

美好的一天,

我想知道如何保护我的网站免受ajax垃圾邮件的攻击。我希望限制任何ajax动作 用户。让我们说每分钟8次ajax动作。

行动的一个例子是:添加/删除博客帖子的按钮“作为我的最爱”。

除非我错了,我相信最好的方法是使用$_SESSION的变量并避免某人/机器人清除 饼干,以避免我的保护。我只允许登录用户使用ajax函数。

使用数据库会使我的保护无用,因为这是我想要避免的不需要的数据库写入。

我必须提到我实际上使用 PHP 作为服务器语言和 jQuery 来进行我的ajax调用。

谢谢

修改

Sentense

  

...保护我的网站......

令人困惑,但它不是关于跨域的ajax。

编辑2011-04-20: 我添加了50美元的赏金。

8 个答案:

答案 0 :(得分:9)

由于您只允许AJAX操作登录用户,因此解决起来非常简单。

  • 为每个帐户创建一个时间戳字段。您可以在数据库中执行此操作,也可以使用Memcached,或者使用平面文件。
  • 每次用户通过您的AJAX界面发出请求时,请将当前时间戳添加到您的记录中,并且:
  • 检查以确保最后八个时间戳在一分钟之前不是 all

从那里你可以添加额外的魔法,比如明显违反速度限制的临时账户,或者将违规者的IP与已知垃圾邮件发送者的黑名单等进行比较。

答案 1 :(得分:1)

您是在谈论针对您网站的特定ajax垃圾邮件,还是一般的ajax垃圾邮件?

如果是后者,你可以使用哈希来阻止自动发送表单,即编写你的hash()单向函数,该函数接受字符串并对其进行sha1校验和。

这就是你如何使用它:

// the page is a blog post #357
$id = 357;
$type = 'post';
$hash = hash($_SERVER['REMOTE_ADDR'].$type.$id);

将该哈希值放在注释表单中的的隐藏字段中,甚至隐藏在页面底部某处的隐藏div中,并将其命名为“control_hash”或其他内容。将它的值附加到表单提交的ajax请求中。当脚本收到表单时,请从$_REQUEST数据(不包括现有$control_hash)创建新哈希,并检查它们是否匹配。

如果表单是由bot提交的,则不会有$control_hash,因此它不会通过。

答案 2 :(得分:0)

是的,你的理念原则上是好的。有些事情需要考虑:

  • 如果您全局跟踪限制,那么您可能会遇到机器DoS问题,并阻止合法用户使用“收藏夹”按钮。
  • 如果您根据他们的IP跟踪请求,那么有人可以使用僵尸网络(多个IP)来绕过您的阻止。根据您的网站和您的偏好,可能会根据subnet of the IP
  • 进行限制
  • 安装并使用Memcache来存储和跟踪请求,尤其是在您要基于IP进行跟踪时。这应该比使用会话变量更快(有人可能会纠正我)。

答案 3 :(得分:0)

如果您可以访问网站的源代码,则可以重写一些实际执行AJAX请求的JavaScript代码。即您的页面可以有一个隐藏的计数器字段,每次用户单击该按钮时都会递增。此外,您还可以在页面上隐藏时间字段,以便对点击次数进行评级。

这个想法是你根本不需要向服务器发送任何内容 - 只需在脚本内的客户端进行检查即可。当然,这无法帮助机器人直接面对服务器。

答案 4 :(得分:0)

这实际上取决于此类垃圾邮件的结果。如果您只是想避免写入数据库,那么所有这些检查最终可能会占用比实际写入数据库更多的资源。

结果是否证明了手段的合理性?

您还必须判断此类垃圾邮件的概率是多少。大多数机器人都不是很聪明,并且当涉及到一些日志记录时会很惨失。

只需2美分,其他答案完全有效,可以避免垃圾邮件。

答案 5 :(得分:0)

购买更强大的托管服务请求,不要限制它们。 每分钟8个请求很荒谬 无论如何,如果请求是“合法的”,您应该找到如何处理请求的方法,而不是如何限制请求。如果不是“合法的” - 然后在没有任何“时间”限制的情况下否认它们。

答案 6 :(得分:0)

您可以使用具有全局变量的会话字段,该变量保存上次ajax请求的时间。由于您要允许8个请求,因此请将其设置为大小为8的数组,并检查时间差异。如果它增加,(重要)它可能并不总是机器人。为用户提供验证码或类似的机会。 (可能是数学问题?)

验证验证码后,允许接下来的几个帖子等。

但请确保您正在检查该特定会话和用户。

Kerin的答案很好,我只是想强调验证码。

答案 7 :(得分:0)

是的,你需要在每个函数视图中使用一个函数进行交互,它也应该在全局库中,这样你就可以在任何地方使用它。

if(is_logged_in())
{
    // do you code here 
}

而is_logged in定义如下

function is_logged_in($activated = TRUE)
{
    return $this->ci->session->userdata('status') === ($activated ? STATUS_ACTIVATED : STATUS_NOT_ACTIVATED);
}

您应该在用户成功登录时设置状态会话。