返回介绍

10.3 生成验证码

发布于 2025-01-30 22:11:35 字数 5386 浏览 0 评论 0 收藏 0

通过上一节,我们已经很好的掌握了图像处理的精髓。

通过我们所掌握的知识。进行一些简单的扩展,我们就可以写出:网上最常用的一个小东西——验证码。

验证码是为了防止机器自动注册、机器自动刷票最常用的手段之一。

我们来看一下验证码的效果:
document/2015-09-21/55ff9eef8b3f0

我们根据上面的效果来推理实现的过程。

实现过程:

  1. 生成指定宽高的画布
  2. 准备好字好需要生成的字符串
  3. 每次执行,让背景填充随机的颜色(浅色系)
  4. 在画布上画上随机的干扰元素(随机点、随机线、随机弧形等均可,但不可过份影响用户的视觉)
  5. 写上 4 个文字
  6. 输出 header 头,告知浏览器按照某类型显示
  7. 输出图像
  8. 销毁图像资源

上面的步骤把实现验证码的每一步都讲清楚了。下面我们来根据这个过程来推理实现。

第一步、创建画布

$img = imagecreate($width, $height);

我们可以定义一个自定义的宽和高。做一个函数将,可以通过函数传入宽和高。这样,可以修改验证码图像的大小。

function check_code($width = 100, $height = 50) {

$img = imagecreate($width, $height);

}

第二步、生成验证码显示的文字

验证码的文字通常有数字、字母。而为了区别验证码字符。我们可以用 0-9A-Za-Z。但是 0 和 o,l 和 I 有的时候区分不清楚。我们如果不需要处理,可以想办法去除掉:

方案一:
循环 4 个 ascii 码,而 ascii 码,而 chr 或者 sprintf('%c',第二个参数传 ascii 码) 将对应的字符转为指定的字符。

  for ($i = 0; $i < $num; $i++) {
  $rand = mt_rand(0, 2);
  switch ($rand) {
    case 0:
      $ascii = mt_rand(48, 57); //0-9
      break;
    case 1:
      $ascii = mt_rand(65, 90); //A-Z
      break;

    case 2:
      $ascii = mt_rand(97, 122); //a-z
      break;
  }
  //chr()
  $string .= sprintf('%c', $ascii);
}

方案二:
方案一对很多人来说有点复杂,很多人理解不了 ascci 码。有没有更简单的方案呢。单然有。我可以准备好字符,然后用 str_shuffle 打乱字符后使用 substr 进行截取。

//没有 0,i,l,o
$str = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789';

$str = str_shuffle($str);

$string = substr($str,0 ,3);

三、 每次执行,让背景填充随机的颜色(浅色系)

文字是深色的看得清楚,而背景是潜色的。

背景的 RGB 颜色表示通常是这样的,RGB 颜色是三个色值,这三个色值都是从 0-255。

而:
0-120 低数值是深色系。
130 - 255 通常为浅色系。

使用到图片颜色的地方挺多的。因此,我可以定义分配颜色的功能:

//浅色的背景函数
function randBg($img) {
return imagecolorallocate($img, mt_rand(130, 255), mt_rand(130, 255), mt_rand(130, 255));
}

//深色函数,深色的字或者点这些干 扰元素
function randPix($img) {
return imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120));
}

四、在画布上画上随机的干扰元素

我们可以随机的在图片中画上 50 个像素点。最小的位置为 0,0。最大的位置为最大的宽或者最大的高。

然后使用 mt_rand(0,最大宽)、mt_rand(0,最大高)。再使用 randPix 针对我们创建的画布来分配颜色。

  //画干扰元素

for ($i = 0; $i < 50; $i++) {

  imagesetpixel($img, mt_rand(0, $width), mt_rand(0, $height), randPix($img));

}

五、写上 4 个文字

$string 是一个字符串,字符串$string[0]为字符的第一个字符,依此类类推。

因此,我可在使用 imagechar 函数在图像中写入文字。

而写入文字的 x,y 的坐标我们可以用一个公式推倒出来。

X 位置 = 图像宽/字符个数(4) * 循环次数。 得到的结果取整后再乘以每次循环的次数。假设图像为 100 个宽度,那么:第一次写在 0 的位置,第二次为 25,第三次为 50,第四次为 75。

Y 位置 = mt_rand(0,图像高- 15)。

我们可以推导出下面的代码,就可以写出对应的文字了:

  for ($i = 0; $i < $num; $i++) {
  $x = floor($width / $num) * $i;
  $y = mt_rand(0, $height - 15);

  imagechar($img, 5, $x, $y, $string[$i], randPix($img));

}

六、输出 header 头,告知浏览器按照某类型显示

我们知道图像类型的输出函数都有:imagejpeg,imagepng,imagegif 等特点。

而图像的 mime 类型为 image/jpeg,image/png,image/gif 等。

因此,我们可以声明一个变量:

$imagetype = 'jpeg';
$imagetype = 'png';
$imagetype = 'gif';

输出 header 类型的时候执行:

$header = 'Content-type:image/' . $imagetype;

执行函数输出的可以拼接出一个变量函数:
$func = 'image' . $type;

如果我们的系统支持个类型,则使用 function_exists 检测函数是否存在。存在则系统支持该类型,不存在则不支持该类型。

所以代码可以写成这样:

  $func = 'image' . $type;

$header = 'Content-type:image/' . $type;

if (function_exists($func)) {
  header($header);
  //变为了 imagejpeg 等
  $func($img);
} else {

  echo '图片类型不支持';
}

八、销毁资源,返回字符

以后在验证的时候,大家需要把验证码显示出来。并且,用户输出的验证字符还需要与图像中的验证字符匹配。

所以要将验证字符返回回来,供以后保存使用。

  imagedestroy($img);
return $string;

我们来看一下全部的准备完成的 PHP 函数文件,我们将上面的代码封装成一个统一的函数供大家来学习使用:

<?php

check_code();

function check_code($width = 100, $height = 50, $num = 4, $type = 'jpeg') {

$img = imagecreate($width, $height);
$string = '';
for ($i = 0; $i < $num; $i++) {
  $rand = mt_rand(0, 2);
  switch ($rand) {
    case 0:
      $ascii = mt_rand(48, 57); //0-9
      break;
    case 1:
      $ascii = mt_rand(65, 90); //A-Z
      break;

    case 2:
      $ascii = mt_rand(97, 122); //a-z
      break;
  }
  //chr()
  $string .= sprintf('%c', $ascii);

}
//背景颜色
imagefilledrectangle($img, 0, 0, $width, $height, randBg($img));

//画干扰元素

for ($i = 0; $i < 50; $i++) {

  imagesetpixel($img, mt_rand(0, $width), mt_rand(0, $height), randPix($img));

}
//写字
for ($i = 0; $i < $num; $i++) {
  $x = floor($width / $num) * $i + 2;
  $y = mt_rand(0, $height - 15);

  imagechar($img, 5, $x, $y, $string[$i], randPix($img));

}

//imagejpeg

$func = 'image' . $type;

$header = 'Content-type:image/' . $type;

if (function_exists($func)) {
  header($header);
  $func($img);
} else {

  echo '图片类型不支持';
}
imagedestroy($img);
return $string;

}
//浅色的背景
function randBg($img) {
return imagecolorallocate($img, mt_rand(130, 255), mt_rand(130, 255), mt_rand(130, 255));
}
//深色的字或者点这些干 扰元素
function randPix($img) {
return imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120));
}

?>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文