8

我经营一个游戏网站,所以我有很多用户登录,他们可以每两分钟做一次某些事情。

我在一些地方有一个 CAPTCHA 系统,对于某些事情,它总是会要求输入代码,而对于其他事情,它会每 10 分钟询问一次。

我让一些玩家使用了 Opera 的自动提交功能,而我的验证码系统确实阻止了他们。

我的问题是,我怎样才能最大限度地减少我要求代码的次数,但仍然阻止人们使用这个自动提交?

4

2 回答 2

6

如果我理解正确,此任务不需要验证码。我假设您想查看用户是否确实单击了自己,坐在他的 PC 前。

新理念

在您的表单上提交多个图像:

<input type="image" name="send1" src="buttons.php?i=1" />
...
<input type="image" name="send8" src="buttons.php?i=8" />

生成表单时,获取 1 到 8 之间的随机数并将其保存在$_SESSION['submitnumber']. 创建两个相同大小的图像 - 一个空的填充了您在表单中的默认背景,另一个看起来像一个提交按钮。创建将使用以下代码输出图像的buttons.php:

header("Content-Type: image/jpeg");
flush();
readfile($filename);

$_GET[i]!=$_SESSION['submitnumber']如果else 返回提交图像,则返回空图像。

如果单击了正确的图像提交,则接受表单(当用户单击按钮时,浏览器将向您发送类似 send1X 的坐标)

这是一种验证码,但人们不会知道;)

旧观念

你需要两件事:

1为非常独特的表单生成令牌。

放置<input type="hidden" name="timertoken" value="someweirdstring" /> 并生成“someweirdstring”作为某些(用户名和时间)相关事物的 md5 哈希。我可以详细说明一下,但这是用于安全和 CSRF 攻击阻止的基本形式令牌。发布后验证令牌。

例子:

不是令牌机制的典型实现,但已经足够了。

$token=generatesomerandomtext();
$_SESSION['token']=$token; 

//... somewhere later when outputing forms:    
echo '<input type="hidden" name="token" value="'.$token.'" />';

//and when it comes back:
if($_POST['token']==$_SESSION['token']) {
   //it's ok
   }

这就是你所需要的。这个简单的示例为每个页面创建一个唯一的令牌并放入表单。它不依赖于时间并且不使用 md5,而是将令牌存储在会话中。要自动发送将被接受的表格,该人必须使用您生成的表格或复制令牌。

真正的表单令牌示例将更像这样: $token=md5($username.'some secret text'.$date.$timeRoundedTo10Minutes);

//... somewhere later when outputing forms:    
echo '<input type="hidden" name="token" value="'.$token.'" />';

//and when it comes back:
if(
 ($_POST['token']==md5($username.'some secret text'.$date.$timeRoundedTo10Minutes)) ||
 ($_POST['token']==md5($username.'some secret text'.$date.$timeRoundedTo10Minutes-10minutes)) ) {
   //it's ok
   }

为什么是用户名?因为它消除了使用一个用户的令牌来破解另一个用户的可能性 为什么要使用秘密文本(称为“salt”)?因为有人可以将其他用户的名字与时间粘在一起并执行 md5,但无需猜测他不能猜到的盐。为什么要进行两次比较?因为如果现在是 22:44:59 - 令牌是在 22:40 生成的,如果用户发送它是 22:45:30,所以它会四舍五入到 22:50 并且只有当你收回 10 分钟时它才匹配令牌.

这就是一个基本的例子。供参考,请参阅问题。

2将您的提交按钮更改<input type="image" ...为发布按钮单击位置的 x 和 y 坐标。我不知道谁在规范中提出了这个,但这是第一次可以使用它!:)

现在看看用户是否点击了自己你只需要看看坐标是否存在(经典提交不会发送它们)并阻止简单的黑客攻击你还可以记住玩家会话中的最后一个 x 和 y 并进行比较。破解它以每次发送不同的坐标要困难得多。

表单标记用于防止用户准备带有随机字段的表单副本,这些字段会模拟点击坐标。如果令牌每次都更改,则很难覆盖表单字段。

这仍然可以通过用户脚本功能破解,但要困难得多。如果您在一小时内添加一次验证码,那么没有人会费心编写仅能帮助一个小时并在此之后中断的脚本(并且需要一些努力和知识)。

于 2010-04-19T17:49:36.100 回答
3

根据您收到的数据,您可以收集来电者是用户的证据。如果来电者似乎是机器人,请仅询问 CAPTCHA。

证据可以是:

  • 用户代理(不可靠,因为 Opera 可以伪造这个)
  • 触发提交的时间间隔(调用越准确,即每 2 分钟一次,它就越有可能是机器人)
  • 如果您的数据允许检查返回模式,那也很明显
  • ...
于 2010-04-08T13:08:09.510 回答