《PHP基于GD库制作图形验证码》

说在前头:本人为大二在读学生,书写文章的目的是为了对自己掌握的知识和技术进行一定的记录,同时乐于与大家一起分享,因本人资历尚浅,能力有限,文章难免存在一些错漏之处,还请阅读此文章的大牛们见谅与斧正。若在阅读时有任何的问题,也可通过评论提出,本人将根据自身能力对问题进行一定的解答。

前言

验证码的作用:网站上的验证码的作用是保护网站安全,一般网站都要通过验证码来防止机器大规模注册,机器暴力破解数据密码等危害。手机的短信和语音验证码是要确定这个手机是用户自己的。其实最后都是为了验证,这个操作是个人在做而不是机器,证明我是我的过程。接下来我们就通过PHP的GD库生成一个图形验证码。

制作图形验证码前对技能储备的要求:对php,和html的语法有一定的了解。

1.开启PHP的GD库扩展

使用GD库制作验证码前,需要开启PHP的GD库扩展,我们可以通过phpinfo();函数查看自己的php是否已经开启GD库扩展(如下)

接着我们访问在浏览器访问http://localhost/info.php即可查看到如下界面

按下浏览器自带的查找关键字的快捷键ctrl+f,搜索gd,如下:

搜索结果如上,即您的php已启用GD库扩展,如果没有上面所示的信息,说明php的GD库还未启用,我们需要手动开启GD库扩展。

找到php安装目录,我这边使用的是NMP集成环境,对应的目录为D:\Visual-NMP-x64\Bin\PHP\php-7.0.13-nts-Win32-VC14-x64(路径只用于参考)。

找到安装目录后,我们可以找到php的配置文件php.ini(如下图)

打开php.ini文件,找到php_gd2.dll,将该行前的分号“;”去掉,表明你要开启php的GD库。(如下图)


 

2.制作前端页面

由于我们现在只是对制作图形验证码做测试,对于前端的页面我们做的简单一点即可。

前端页面分为主页index.php,以及通知提醒的alert.php两个页面,页面代码可以参考下面的代码。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Index</title>
  <style>
    form {
      position: absolute;
      text-align: center;
      width: 160px;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }
    input {
      width: 160px;
    }
    h4 {
      color: deepskyblue;
    }
    #submit {
      border-radius: 5px;
      color: white;
      width: 160px;
      height: 30px;
      font-weight: bold;
      background: deepskyblue;
    }
    img {
      width: 160px;
      height: 30px;
      border: 1px solid gray;
    }
</style>
</head>
<body>
<form method="post" action="check.php">
  <h4>登&nbsp;&nbsp;录&nbsp;&nbsp;页&nbsp;&nbsp;面</h4>
  <input name="username" type="text" placeholder="用户名"/>
  <br/><br/>
  <input name="password" type="password" placeholder="密码"/>
  <br/><br/>
  <input name="captcha" type="text" placeholder="验证码"/>
  <br/><br/>
  <img src="captcha.php">
  <br/><br/>
  <input id="submit" type="submit" value="登录">
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>提示</title>
</head>
<body>
<script>
  alert("<?php echo $_GET['msg'] ?>");
  history.back();
</script>
</body>
</html>

访问http://localhost/,我们可以看到前端页面效果如下

3.主要函数介绍

imagecreatetruecolor();          // 生成画布函数imagecolorallocate();            // 设置背景颜色函数imagefill();                     // 画面填充函数imagesetpixel();                 // 生成点图形的函数imageline();                     // 生成线条图形的函数header('content-type:image.png');// 设置图片输出格式为pngimagepng($image);                // 以png的格式输出图片imagedestroy($image);            // 销毁图片

4.开始制作验证码

①:创建captcha.php文件用于生成验证码图片

②:创建画布

<?php
// 创建宽为160px,高为30px的画布
$image = imagecreatetruecolor(160, 30);
// 设置背景颜色为白色
$bg_color = imagecolorallocate($image, 255, 255, 255);
imagefill($image,0,0,$bg_color);
​
// 以png的格式输出
header('content-type:image.png');
imagepng($image);
​
// 销毁图片
imagedestroy($image);
?>

访问http://localhost/,我们可以看到,页面已经生成了一张全白的验证码图片

③:接下来我们需要对空白的验证码图片中添加验证码信息,代码如下

<?php
​
// 创建宽为160px,高为30px的画布
$image = imagecreatetruecolor(160, 30);
// 设置背景颜色为白色
$bg_color = imagecolorallocate($image, 255, 255, 255);
imagefill($image,0,0,$bg_color);
​
// 字母和数字混合验证码
for($i = 0; $i < 4; $i++) {
    $font_size = 10;
    $font_color = imagecolorallocate($image, rand(0, 120), rand(0, 120), rand(0, 120));
    $data = 'abcdefghijklmnopqrstuvwxyz1234567890';// 验证码字典
    $font_content = substr($data, rand(0, strlen($data)), 1);
    $x = ($i * 160 / 4) + rand(5, 10);
    $y = rand(5, 10);
    imagestring($image, $font_size, $x, $y, $font_content, $font_color);
}
​
// 以png的格式输出
header('content-type:image.png');
imagepng($image);
​
// 销毁图片
imagedestroy($image);
​
?>

访问http://localhost/,空白的画布上已经出现了四位字母和数字混合的验证码信息。

④:我们还需要对验证码添加以下干扰因素(降低机器识别验证码的成功概率),先加数十位颜色各异的点(代码如下)

<?php
​
// 创建宽为160px,高为30px的画布
$image = imagecreatetruecolor(160, 30);
// 设置背景颜色为白色
$bg_color = imagecolorallocate($image, 255, 255, 255);
imagefill($image,0,0,$bg_color);
​
// 字母和数字混合验证码
for($i = 0; $i < 4; $i++) {
    $font_size = 10;
    $font_color = imagecolorallocate($image, rand(0, 120), rand(0, 120), rand(0, 120));
    $data = 'abcdefghijklmnopqrstuvwxyz1234567890';// 验证码字典
    $font_content = substr($data, rand(0, strlen($data)), 1);
    $x = ($i * 160 / 4) + rand(5, 10);
    $y = rand(5, 10);
    imagestring($image, $font_size, $x, $y, $font_content, $font_color);
}
​
// 增加干扰点
for($i = 0 ; $i < 200; $i++){
    $point_color = imagecolorallocate($image,rand(50,200),rand(50,200),rand(50,200));
    imagesetpixel($image, rand(1, 159), rand(1, 29), $point_color);//
}
​
// 以png的格式输出
header('content-type:image.png');
imagepng($image);
​
// 销毁图片
imagedestroy($image);
?>

访问http://localhost/,验证码图片在原来的基础上,增多了许多干扰点

⑤:为了进一步降低机器识别验证码的成功概率,最后我们再添加几条干扰线,代码如下

<?php
​
// 创建宽为160px,高为30px的画布
$image = imagecreatetruecolor(160, 30);
// 设置背景颜色为白色
$bg_color = imagecolorallocate($image, 255, 255, 255);
imagefill($image,0,0,$bg_color);
​
// 字母和数字混合验证码
for($i = 0; $i < 4; $i++) {
    $font_size = 10;
    $font_color = imagecolorallocate($image, rand(0, 120), rand(0, 120), rand(0, 120));
    $data = 'abcdefghijklmnopqrstuvwxyz1234567890';// 验证码字典
    $font_content = substr($data, rand(0, strlen($data)), 1);
    $x = ($i * 160 / 4) + rand(5, 10);
    $y = rand(5, 10);
    imagestring($image, $font_size, $x, $y, $font_content, $font_color);
}
​
// 增加干扰点
for($i = 0 ; $i < 200; $i++){
    $point_color = imagecolorallocate($image,rand(50,200),rand(50,200),rand(50,200));
    imagesetpixel($image, rand(1, 159), rand(1, 29), $point_color);//
}
​
// 增加干扰线
for($i = 0; $i < 3; $i++){
    $line_color = imagecolorallocate($image, rand(80, 280), rand(80, 220), rand(80, 220));
    imageline($image, rand(1, 159), rand(1, 29), rand(1, 99), rand(1, 29), $line_color);
}
​
// 以png的格式输出
header('content-type:image.png');
imagepng($image);
​
// 销毁图片
imagedestroy($image);
​
?>

访问http://localhost/,验证码图片成为了我们想要的摸样了

至此,我们的验证码图片已经完善,但对于验证码信息的判断我们一直未思考,我们需要使用一个全局的变量保存验证码信息,然后使用这个全局的变量与用户的输入的验证码信息进行判断。在浏览器中我们有什么是全局的变量?我们可以使用session保存我们的变量,当需要与用户输入的验证码验证时,从session中取出与之匹配。

⑥:对此我们对我们的captcha.php代码进行修改,如下:

<?php
​
session_start();// 开启会话
​
// 创建宽为160px,高为30px的画布
$image = imagecreatetruecolor(160, 30);
// 设置背景颜色为白色
$bg_color = imagecolorallocate($image, 255, 255, 255);
imagefill($image,0,0,$bg_color);
​
$captcha='';// 存储验证码
​
// 字母和数字混合验证码
for($i = 0; $i < 4; $i++) {
    $font_size = 10;
    $font_color = imagecolorallocate($image, rand(0, 120), rand(0, 120), rand(0, 120));
    $data = 'abcdefghijklmnopqrstuvwxyz1234567890';
    $font_content = substr($data, rand(0, strlen($data)), 1);
    $captcha.=$font_content;
    $x = ($i * 160 / 4) + rand(5, 10);
    $y = rand(5, 10);
    imagestring($image, $font_size, $x, $y, $font_content, $font_color);
}
​
// 使用session保存验证码信息,用于后续验证
$_SESSION['captcha']=$captcha;
​
// 增加干扰点
for($i = 0 ; $i < 200; $i++){
    $point_color = imagecolorallocate($image,rand(50,200),rand(50,200),rand(50,200));
    imagesetpixel($image, rand(1, 159), rand(1, 29), $point_color);//
}
​
// 增加干扰线
for($i = 0; $i < 3; $i++){
    $line_color = imagecolorallocate($image, rand(80, 280), rand(80, 220), rand(80, 220));
    imageline($image, rand(1, 159), rand(1, 29), rand(1, 99), rand(1, 29), $line_color);
}
​
// 以png的格式输出
header('content-type:image.png');
imagepng($image);
​
// 销毁图片
imagedestroy($image);
​
?>

至此,captcha.php文件生成验证码的代码已经完善。

 4.后台验证

创建check.php文件做后台逻辑处理验证(用户名与密码使用固定的test:123456),代码如下:

<?php
​
session_start();// 开启会话
​
$db_username = "test";
$db_password = "123456";
​
$username = $_REQUEST['username'];
$password = $_REQUEST['password'];
$captcha = $_REQUEST['captcha'];
​
if ($username == "" || $password == "") {
    header('location:alert.php?msg=用户名密码不能为空');
    exit();
}
if ($captcha == "") {
    header('location:alert.php?msg=验证码不能为空');
    exit();
}
if ($captcha != $_SESSION['captcha']) {
    header('location:alert.php?msg=验证码错误');
    exit();
}
if ($db_username == $username && $db_password == $password) {
    header('location:alert.php?msg=登录成功');
    exit();
}
header('location:alert.php?msg=登录失败');
?>

5.测试

访问http://localhost/,开始进行测试。

可以看到,验证码内容为,"6d9o",此时我们输入在用户名处输入test,密码输入123456,验证码为空,点击登录后会得到以下提示(“验证码不能为空”)。

接下来,输入错的验证码

点击登录,得到提示(“验证码错误”)。

输入正确验证码点击登录

得到提示(“登录成功”)。


总结

相信对于php与html语法有基本了解的小伙伴们,此技术应该很好理解,也希望此文章对你们有所帮助。若文章中有错漏之处,还请您的斧正。

👇扫描二维码关注

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云丶言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值