CAPTCHA 和军队中使用的口令是一个目的,就是验证对方的身份。在 WebApp 中通常是用来访问者是人而不是机器(或者说程序)。和军队中的口令类似,用户需要正确回答出“口令”的内容才能访问到需要的资源。
CAPTCHA 和 用户密码不同。用户密码通常由用户自己设置,并且用户密码通常在一个会话过程中不会改变。而 CAPTCHA 则由服务器随机生成,并给用户一个提示信息,用户根据提示信息输入“口令”。可以看出对于 CAPTCHA 来说,有着下面的要求:
在这样的要求下,目前常用的方案是要求用户输入图片中的字符串(数字)。当然这背后的假设就是用利用程序识别出图片上的字符串不是件容易的事情。甚至为了减少被程序识别的可能,图片上的字符常常作了变形处理。
当然,并非只有图片可以用来作为提示信息,语音也可以用。甚至要求不高的话,纯文本也可以。比如显示一个数学计算 13+12 =?
,要求用户输入计算结果。
明白了 CAPTCHA 的原理,实现就也不是什么复杂的事情。下面的例子就用 PHP 实现上面数学计算的例子。
// 显示“提示信息" function captcha(){ $a = rand(0,50); $b = rand(0,50); $op = rand(1,100)>50?'+':'-'; $v = ($op == '+')?($a+$b):($a-$b); $_SESSION['auth']['captcha'] = $v; return "$a $op $b = ?"; } // 验证用户答案 function verify_captcha(){ return ($_SESSION['auth']['captcha'] == $_POST['captcha']); } if(! verify_captcha()){ // 验证失败 }else{ // 验证成功 }
上面的例子由于是文本的提示信息,可以把生成提示信息和验证答案的代码写在一个脚本里。如果是用图片或者声音作为提示信息的话,就要有一个单独的脚本来生成图片内容。但有一点是一样的,就是大家都是通过 Session 来保存正确答案。
上面的例子,实际上在同一个 Session 中只允许一个CAPTCHA 实例存在。也许你希望用户可以同时访问不同的页面,并看到不同的 CAPTCHA,那就需要多一些数据结构上的考虑。当然这样做的意义也许并不大。但如果确有需要,可以如下解决。
TODO: 补充更多内容。。。