11

Ok, here is an issue: in the project i'm working on, we can't rely on server-side sessions for any functionality.

The problem is that common captcha solutions from preventing robotic submits require session to store the string to match captcha against.

The question is - is there any way to solve the problem without using sessions? What comes to my mind - is serving hidden form field, containing some hash, along with captcha input field, so that server then can match these two values together. But how can we make this method secure, so that it couldn't be used to break captcha easily.

4

13 回答 13

4

对会话或数据库的需求来自于将图像的 GET 与包含它的 html 页面协调的需要,那么如何使用相同的代码嵌入验证码图像:[img src='data:image/jpeg;base64, ...'],使用随机盐对其文本进行散列,然后在单个 GET 中将随机盐和散列与图像一起发送到客户端?

在回发时,您将用户文本附加到盐,然后比较哈希值。只是想知道这有多安全......

于 2010-04-21T10:19:57.060 回答
2

使用蜜罐 技术:将具有贪心名称的文本字段(如“电子邮件”)放入由 CSS 隐藏的字段中(显示:无;可见性:隐藏;)。

当您必须清理表单时,只需检查该字段是否为空,是否由人发送(看不到该字段,因此无法填写),否则来自垃圾邮件发送者。

这就是为什么垃圾邮件发送者通常在发送表单之前使用预先确定的值填充页面中的所有字段......并且不会打扰用户阅读验证码。

否则,依靠人工阅读,例如“在字段中写入单词“$word”的第一个 $x 字母:”

然后,您只需将 $x 和 $word 发送到下一页并检查它(当然,您可以随机化字段名称以更准确)

我记得phpBB 论坛的插件依赖于这样一个事实,即垃圾邮件机器人通常会选择字段中的第一个可用选项(带有值)<select>;只是作为第一选择<option value="kickmeplease">Yes, im a bot.</option>

有很多方法可以防止垃圾邮件机器人,发挥机器人永远不会拥有的一个因素:想象力

于 2010-03-27T02:05:33.627 回答
1

让 CAPTCHA 生成器返回图像,并使用盐渍散列或自定义散列作为答案(强调盐渍/自定义)。让生成器将该哈希推送到 cookie 中。然后,服务器可以根据 cookie 中的值进行验证。这不需要 JavaScript,但如果 cookie 被禁用,您将不得不回退到另一种技术。

于 2011-09-12T18:45:33.870 回答
1

自动填充验证码的 UUID 以及 POST 中的用户答案。十分简单。

于 2012-12-10T20:33:15.057 回答
1

只需做一个数学验证码;) 2+90 = ? 方程应该显示在图像中,瞧;)

于 2013-11-03T22:43:02.330 回答
1

您可以尝试在数据库中存储一堆验证码。或者,这里对替代验证码方法进行了很好的讨论:实用的非基于图像的验证码方法?

确实有一些非常有趣的技术,请通读。

于 2009-09-23T12:37:40.190 回答
1

如果没有持久状态服务器端,我看不到验证码在工作。

您的建议并不安全,因为攻击者总是可以轻松地发布他自己的带有匹配验证码文本的“隐藏字段”。

为什么不从另一个可以拥有持久状态的网络服务器进行验证码呢?

于 2009-09-23T12:43:39.850 回答
0

使您的隐藏输入字段只是一个随机序列。将此随机数据与验证码信息一起存储在数据库中,以便您可以使用它查找正确的验证码。

您还需要为生成的每个验证码设置一个较短的生存时间。最后,您可以在数据库中存储和跟踪每个验证码的尝试次数,并对其施加硬限制(3 次猜测,这是永久失败)。

于 2009-09-23T12:40:34.027 回答
0

我自己的想法,不知道好不好:

1)如果用户登录,只需在他的登录上使用一些哈希函数并用它生成验证码,

2)如果它是注册表单等,只需从表单字段中散列一些值(例如登录,当用户完成输入时)并通过 ajax 显示带有来自登录的散列的 CAPTCHA。

希望,这是可以理解的。:)

编辑: 没有 AJAX:2 步注册:

1,我们收集登录等提交后,我们直接到?login=new_login

在 2 处,我们GET["login"]在 CAPTCHA 图像中隐藏了输入并从中散列 - 提交后,我们必须检查答案。

于 2009-09-23T12:48:32.803 回答
0

您可以授予他们客户端证书以响应 CAPTCHA 调用吗?然后,一旦他们在浏览器中选择了该证书,它就会随客户端的每次调用一起发送,并且可以在没有会话和进一步 CAPTCHA 调用的情况下用于身份验证。

于 2009-09-23T13:01:02.267 回答
0

这是我的看法(如果看起来很复杂,请原谅):

  1. 页面请求:

    • 你生成一个随机字符串代码'abcdef';
    • 您使用一些预定义的密码加密代码: $crypt = encrypt($captcha_code, 'password')
  2. 形式:

    • 图像链接被发送到浏览器'captcha.php?$crypt'
    • 使用 $crypt 的值设置隐藏输入
  3. captcha.php 页面对加密文本进行解密,并生成图像。

  4. 用户提交带有代码“abcdaa”的表单(以及隐藏的输入 $crypt)

  5. 服务器验证 encrypt('abcdaa') == $crypt

编辑:加密功能需要是可逆的(解密),因为验证码图像生成器将需要原始代码。

于 2009-09-23T13:30:05.167 回答
0

这个解决方案怎么样?我在谷歌上找到了这篇“无会话 PHP 验证码”文章,并在我的一个项目中使用过,它很简单,没有会话,而且是免费的。RC4 有任何安全问题吗?

http://www.mythos-rini.com/blog/archives/732

于 2010-03-27T00:36:45.827 回答
0

带有验证的表单:

$errorsucc = '';

if (isset($_POST["captcha_check"])) {

    $code = str_decrypt($_POST["captcha_check"]);   

    if (empty($_POST['captcha_code'])) { 
        $errorsucc = '<p style="color:red">Please Enter the security code.</p>';

    } elseif(!( $code == $_POST['captcha_code'] && !empty($code) )) {
        $errorsucc = '<p style="color:red">Incorrect Code Entered.</p>';

    } else {
        $errorsucc = '<p style = "green">Nice, you entered the correct code.</p>';  
    }
}

$captcha = new CaptchaCode();
$code = str_encrypt($captcha->generateCode(6));
?>

<html>
    <title>Sessionless Captcha</title>
    <div style = "background: #e2e2e2; padding: 20px; width: 20%; box-shadow: 5px 5px #ccc;">
        <?php echo $errorsucc; ?>
        <form name="captchaform" method="post">
            <table border="0" cellpadding="4" cellspacing="0">
                <tr><td valign="middle" align="left">Security Code:</td>
                    <td valign="middle" align="left"><img src="captcha_images.php?width=150&height=50&code=<?php echo $code?>" /></td>
                </tr>
                <tr><td valign="middle" align="left">Enter Code:</td>
                    <td valign="middle" align="left"><input id="captcha_code" name="captcha_code" style="width:150px" type="text" /></td>
                </tr>

                <tr><td valign="top" align="left">
                    </td>
                    <td valign="top" align="left">
                        <input border="0" type="submit" value="Submit" />   
                    </td>
                </tr>
            </table>
            <input type="hidden" name="captcha_check" value="<?php echo $code?>" />
        </form>
    </div>
</html>

像任何其他验证码一样生成图像:

/* font size will be 75% of the image height */
    $font_size = $height * 0.75;
    $image = @imagecreate($width, $height) or die('Cannot initialize new GD image stream');
    /* set the colours */
    $background_color = imagecolorallocate($image, 255, 255, 255);
    $text_color = imagecolorallocate($image, 0, 26, 26);
    $noise_color = imagecolorallocate($image, 25, 89, 89);
    /* generate random dots in background */
    for( $i=0; $i<($width*$height)/3; $i++ ) {
        imagefilledellipse($image, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $noise_color);
    }
    /* generate random lines in background */
    for( $i=0; $i<($width*$height)/150; $i++ ) {
        imageline($image, mt_rand(0,$width), mt_rand(0,$height), mt_rand(0,$width), mt_rand(0,$height), $noise_color);
    }
    /* create textbox and add text */
    $textbox = imagettfbbox($font_size, 0, $this->font, $code) or die('Error in imagettfbbox function');
    $x = ($width - $textbox[4])/2;
    $y = ($height - $textbox[5])/2;
    imagettftext($image, $font_size, 0, $x, $y, $text_color, $this->font , $code) or die('Error in imagettftext function');
    /* output captcha image to browser */
    header('Content-Type: image/jpeg');
    imagejpeg($image);
    imagedestroy($image);

从此链接下载演示文件: 在 PHP 中创建无会话验证码

于 2015-01-09T07:59:25.797 回答