没有会话的PHP Captcha

时间:2009-09-23 12:32:32

标签: php captcha

好的,这是一个问题:在我正在开发的项目中,我们不能依赖服务器端会话来实现任何功能。

问题在于,防止机器人提交的常见验证码解决方案需要会话来存储字符串以匹配验证码。

问题是 - 有没有办法在不使用会话的情况下解决问题?我想到的是 - 提供隐藏的表单字段,包含一些哈希值以及验证码输入字段,以便服务器可以将这两个值匹配在一起。但是我们怎样才能使这种方法安全,这样它就不能用来轻易破解验证码。

13 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:2)

使用honeypot technique :将带有贪婪名称的文本字段(如“电子邮件”)放入CSS隐藏的字段中(显示:无;可见性:隐藏;。)

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

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

否则,请依赖人类阅读,例如“在字段中写下单词”$ word“的第一个$ x字母:”

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

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

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

答案 2 :(得分:1)

您可以尝试在数据库中存储一堆验证码。或者,这里有关于备用验证码方法的讨论:Practical non-image based CAPTCHA approaches?

一些非常有趣的技术,请仔细阅读。

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

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

您建议的内容并不安全,因为攻击者可以轻松地使用匹配的CAPTCHA文本发布自己的“隐藏字段”。

为什么不从另一个可以拥有持久状态的网络服务器上执行CAPTCHA?

答案 7 :(得分:0)

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

1)如果用户被登录,只需在登录时使用一些哈希函数并用它生成CAPTCHA,

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

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

修改 没有AJAX: 2步注册:

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

在2,我们在CAPTCHA图像中隐藏了GET["login"]的输入和哈希值 - 提交后我们都要检查答案。

答案 8 :(得分:0)

您是否可以根据CAPTCHA电话向他们授予客户证书?然后,一旦他们在浏览器中选择了该证书,它就会随客户端的每次呼叫一起发送,并且无需会话即可用于身份验证,而无需进一步的CAPTCHA呼叫。

答案 9 :(得分:0)

这是我对它的看法(如果看起来很复杂,则为sry):

  1. 页面请求:

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

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

  4. 用户提交代码为'abcdaa'的表单(以及隐藏的输入$ crypt)

  5. 服务器验证加密('abcdaa')== $ crypt
  6. 编辑: 加密函数需要是可逆的(解密),因为验证码图像生成器需要原始代码。

答案 10 :(得分:0)

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

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

答案 11 :(得分:0)

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

答案 12 :(得分: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);

从此链接下载演示文件: Create a Sessionless Captcha in PHP