验证码是一种区分用户的全自动程序,它可以有效防止黑客对于特定程序的暴力破解。
最常用的CAPTCHA测试是图形验证码,程序将随机生成一串文字或数字,再将其进行扭曲变形或进行干扰处理(避免被光学字符识别程序破解),最后将输入文字和标准文字进行比较,从而确定用户身份。
借助于一个名为GD(Graphics Draw)的图形库,PHP脚本可以采用图片格式动态生成图像。
生成验证码文本序列
首先要确定文本序列长度,可以使用一个常量表示口令长度,通常6-8个字符就足够了,这样既可以阻止机器人,同时也不会惹恼人类。
define("CAPTCHA_NUMCHARS", 6);
接下来需要随机生成每一个字符,rand() 函数在其参数指定范围内返回一个随机数,chr() 将一个数字ASCII字符码转换为一个真正的字符。
chr(rand(97, 122)); //将随机生成字母a-z
图形函数可视化显示图像
首先需要在内存中创建一个空图像,准备由其他GD函数在它之上进行绘制。
$image = imagecreatetruecolor(width:int,height:int);
分配主题颜色,第一个参数是图像资源标识,后面三个参数表示RGB数值分量。
imagecolorallocate(image:resource,red:int,green:int,blue:int);
在图像中一个指定的坐标上绘制一个像素,最后一个参数传入颜色资源标识。
imagesetpixel(image:resource,x:int,y:int,color:int);
在两个坐标之间绘制一条直线,坐标是相对于图像左上角指定的,最后一个参数控制绘制的颜色。
imageline(image:resource,x1:int,y1:int,x2:int,y2:int,color:int);
用某种指定的颜色填充一个矩形,矩形大小由 (x1,y1) 与 (x2,y2) 决定。
imagefilledrectangle(image:resource,x1:int,y1:int,x2:int,y2:int,color:int);
绘制圆和椭圆,以一个中心点和一个宽度和高度作为参数,椭圆的颜色作为最后一个参数传入。
imagefilledellipse(image:resource,cx:int,cy:int,width:int,height:int,color:int);
完成图像绘制,调用 imagepng() 函数将图像输出。如果选择直接在内存中生成一个PNG图像,那么还必须调用 header() 函数通过一个首部把它传送到浏览器。
header("Content-type: image/png");
imagepng(image:resource);
一旦输出了图像,一定要用 imagedestroy() 释放内存中的图像。
利用图形函数绘制文本
imagestring() 函数很容易用来绘制文本,不过对于文本的外观控制很有限。要得到某种特定的外观,需要使用特殊字体,对于通行短语图像来说,字体外观必须独特,而且最好采用一种粗字体来绘制。
字体文件位于 C:\Windows\Fonts 文件夹下,当然你也可以拷贝一份在你的Web服务器上。
通过 imagettftext() 函数,你不仅可以使用你所选择的任何字体,而且可以控制字体的大小,甚至设置绘制文本的角度。
imagettftext( ) 函数参数:
- 第一个参数是图像资源标识,
- 第二个参数是字体的大小,
- 第三个参数是字体的角度,
- 第四个参数是文本左下角的X坐标,
- 第五个参数是文本左下角的Y坐标,
- 第六个参数是字体颜色,
- 第七个参数是字体文件位置,
- 第八个参数是要绘制的具体文本
生成一个随机的验证码
/* 生成验证码序列 */
define("CAPTCHA_NUMCHARS", 6); //验证码长度
$pass_phrase = ""; //验证码内容
for ($i = 0; $i < CAPTCHA_NUMCHARS; $i++) {
//随机生成字母添加至验证码
$pass_phrase .= chr(rand(97, 122));
}
/* 生成验证码图像 */
define("CAPTCHA_WIDTH", 300); //验证码宽度
define("CAPTCHA_HEIGHT", 100); //验证码高度
//创建空白画布
$img = imagecreatetruecolor(CAPTCHA_WIDTH, CAPTCHA_HEIGHT);
//设置主题颜色
$bg_color = imagecolorallocate($img, 225, 225, 225); //白色背景
$text_color = imagecolorallocate($img, 0, 0, 0); //黑色字体
$graphic_color = imagecolorallocate($img, 64, 64, 64); //灰色图像
//填充背景
imagefilledrectangle($img, 0, 0, CAPTCHA_WIDTH, CAPTCHA_HEIGHT, $bg_color);
//绘制随机直线
for ($i = 0; $i < 10; $i++) {
imageline($img, 0, rand() % CAPTCHA_HEIGHT, CAPTCHA_WIDTH, rand() % CAPTCHA_HEIGHT, $graphic_color);
}
//绘制随机点
for ($i = 0; $i < 20; $i++) {
imagefilledellipse($img, rand() % CAPTCHA_WIDTH, rand() % CAPTCHA_HEIGHT, 10, 10, $graphic_color);
}
//绘制验证码
imagettftext($img, 60, 0, 20, CAPTCHA_HEIGHT - 20, $text_color, "C:/Windows/Fonts/SketchFlow Print.ttf", $pass_phrase);
//作为PNG图像输出
header("Content-type: image/png");
imagepng($img);
//从内存从撤销图像
imagedestroy($img);
问:可以使用GD函数创建PNG以外其他格式的图像吗?
答:可以,使用 imagegif( ) 和 imagejpeg( ) 函数可以分别创建 GIF 和 JPEG 图像。
问:使用 imagepng( ) 直接向浏览器输出一个PNG图像时,图像文件存储在哪里?
答:图像并不存储在任何文件中。实际上,imagepng( ) 函数会在服务器的内存中生成一个二进制PNG图像,然后把它直接通过一个首部传送到浏览器。
问:生成图形的PHP脚本能否直接放在<img>标签的src属性中?
答:在<img>标签的src属性中引用一个PHP脚本时,会由脚本直接传送图像。脚本会通过一个首部将图像直接传送到浏览器,而浏览器会把来自首部的图像连接到<img>标记。