【问题标题】:PHP Verification Codes CAPTCHAPHP 验证码 CAPTCHA
【发布时间】:2010-04-08 12:34:58
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我想我有一个非验证码解决方案的想法,但我需要更多细节。他们如何使用自动提交?你想阻止他们做什么?提交太快、太频繁,还是在离开键盘时提交?
  • 我决定现在发表我的想法,但你仍然可以回答

标签: php captcha user-presence


【解决方案1】:

如果我理解正确,此任务不需要验证码。 我假设你想看看用户是否点击了自己,坐在他的电脑前。

新想法

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

<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']返回空图像,否则返回提交图像。

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

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

老想法

你需要两件事:

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

输入&lt;input type="hidden" name="timertoken" value="someweirdstring" /&gt; 并将“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.'一些密文'.$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
   }

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

这就是一个基本示例。如需参考,请参阅this 问题。

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

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

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

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

【讨论】:

  • 期待总比什么都不做要好,不是吗?如果他们使用键盘,他们将看到与现在相同的验证码。而且,如果您编写了一行在输入时停止提交的 javascript,那么它只会忽略 lynx-alikes。如果 Hinek 使用验证码,它们已经不受支持,对吧?
  • 你能写更多关于这些令牌的信息吗?我有时在一页上有多个表单,这会导致问题吗?您的意思是生成令牌并将其存储在我的数据库中,然后将其添加到表单中,然后相互检查它们吗?还是只存储最后收到的令牌并检查他们是否两次发布相同的令牌?
  • 我建议您找一篇关于这方面的好文章。它的基本工作原理是生成一个特定于表单的文本字符串,将用户名和一些秘密成分粘贴到其中并执行 md5。它不应该留在数据库中。有时人们把它放在会话中,但是当有多种形式时,它会变得复杂,比如你的情况。我会在答案中为你举一个表单标记的小例子。
  • 示例应该有所帮助,但我有一个新想法。等一下;)
【解决方案2】:

根据您收到的数据,您可以收集来电者是用户的证据。仅在调用者似乎是机器人时才要求提供 CAPTCHA。

证据可以是:

  • 用户代理(不可靠,因为 Opera 可以伪造)
  • 触发提交的时间间隔(调用越准确,即每 2 分钟一次,它就越有可能是机器人)
  • 如果您的数据允许检查返回的模式,这也是显而易见的
  • ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2023-03-29
    • 2023-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多