谈谈那些年 PHP 中非常牛的验证码

发布于 2019-11-12 19:27:45 字数 3825 浏览 1466 评论 0

验证码已经是现在网站中非常基础的知识点了,验证码的存在可以防止恶意破解密码、刷票、灌水,可以有效的防止暴力破解特定用户,现在就来了解谈谈那些年PHP中非常牛的验证码。

首先以四位验证码为例(多位验证码一样的道理)。

目前网站大多仍然采用静态图片验证码,因为这样实现起来简单又方便,不需要过硬的功底,当然这也是基础。而其原理也就是通过 PHP 的画图功能将文字画成图片返回到页面。因此我们解决的问题也就只有三步而已:

  1. 随机生成验证码的内容
  2. 将验证码转换成图片,即绘图
  3. 将所绘出的图返回到页面中

当然PHP默认是没有开启绘图功能的,因此在 php.ini 的配置文件中先开启绘图功能,打开 php.ini 文件搜索到:

;extension=php_gd2.dl

将前面的分号去掉即可,保存文件然后重启 Apache 或者 IIS。

那根据第一点,大家首先应该会想到数字的验证码,因为这容易,随机生成个几个数字,然后拼起来也就行了,PHP 大概的实现代码如下:

$validateCode = '';
for ($i = 0; $i < 4; $i ++) {
  $validateCode .= (0, 9);
}
echo $validateCode;

然后仔细想想,现在的网站验证码都有字母,可这玩意儿都没字母,然后又想到,直接把上面那玩意儿搞成十六进制就好了。

$validateCode = '';
for ($i = 0; $i < 4; $i ++) {
  $validateCode .= ((0, 16));
}  
echo $validateCode;

好像有点自作聪明的赶脚呀,不过想想,也算是有几个字母了,可却只有 a,b,c,d,e,f,那要是需要所有字母咋办呢?

再想想也就想到把所有的字母和数字等在一个字符串中列出来,然后通过随机下标的形式去随机获取对应的值,也就成了这样:

$validateCode = '';
$str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
for ($i = 0; $i < 4; $i ++) {
  $validateCode .= $str[(0, ($str))];
}
echo $validateCode;

终于像验证码里的随机数了,不过看到下面的方法,有总瞬间被秒的赶脚:

$str = 'ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456789';
$validateCode = substr(str_shuffle($str), 0, 4);

str_shuffle 方法将字符串内容打乱,substr($str, 0, 4) 取到了前四个数。这样是完全没有问题的!不过细心的看的出来,这样的验证码里的内容是不会重复的。

以上验证码也就产生了,接下来也就要将验证码用 PHP 画出来了。

$str = 'ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456789';
$validateCode = substr(str_shuffle($str), 0, 4);

// 创建一张宽为64px,高为32px的图片
$img = imagecreatetruecolor(64, 32);
// 将图片的背景颜色设置成黑色,颜色值分别对应RGB
$bgcolor = imagecolorallocate($img, 0, 0, 0);

// 创建白色
$white = imagecolorallocate($img, 255, 255, 255);

/* 添加文字在图片中,
第二个参数为文字的大小,只能在1~5
第三个参数为x坐标
第4个参数为y坐标
第5个参数为文字的内容
第6个参数为文字的颜色*/
imagestring($img, 6, 16, 6, $validateCode, $white);

// 返回成图片
header('Content-type: image/png');
imagepng($img);

当然,这样的话验证码就太好识别了,就只是单纯的黑底白字,为了增加点难度,我们就多加几条线叠加在验证码的上面。

$str = 'ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456789';
$validateCode = substr(str_shuffle($str), 0, 4);

// 创建一张宽为64px,高为32px的图片
$img = imagecreatetruecolor(64, 32);
// 将图片的背景颜色设置成黑色,颜色值分别对应RGB
$bgcolor = imagecolorallocate($img, 0, 0, 0);

// 创建白色
$white = imagecolorallocate($img, 255, 255, 255);

for ($i = 0; $i < 30; $i ++) { 
  /* 在图片上画线
  其中第2个参数表示线的x起始坐标
  第3个参数表示线的y起始坐标
  第4个参数表示x的终止坐标
  第5个参数表示y的终止坐标
  第6个参数表示颜色
  此处生成一个随机颜色 */
  $res = imagecolorallocate($img, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
  imageline($img, mt_rand(0, 110), mt_rand(0, 25), mt_rand(0, 110), mt_rand(0, 25), $res);
}

/* 添加文字在图片中,
第二个参数为文字的大小,只能在1~5
第三个参数为x坐标
第4个参数为y坐标
第5个参数为文字的内容
第6个参数为文字的颜色*/
imagestring($img, 6, 16, 6, $validateCode, $white);

// 返回成图片
header('Content-type: image/png');
imagepng($img);

结果也就成了这样,当然要想实现验证码,这样还是不够滴,需要通过将验证码生成的随机数存到服务器的 Session 中,$_SESSION['validate'] = $validateCode; 然后在通过客户端输入的验证码与之对比即可。

PHP 中的验证码也就这样实现了,当然前面也说过了,这是最基础的代码,可以通过你的想法将其改变为实现算术的验证码,中文的验证码,或其它一些有趣的验证码,以减少其枯燥性又实现安全性。

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

4401 文章
128 评论
84972 人气
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。