需求
为了增加安全性,需要一个随机验证码的功能
分析
验证码的功能需要在后端做,因为在前端做就失去意义,比如前端生成验证码,然后前端来验证,那么懂一点的人就可以直接跳过这个向服务器发送请求。而用PHP做验证就不能单纯的生成随机码那么简单,这样别人可以扫描你的字符,然后填进去就可以了,所以这个功能还需要用到PHP得画图功能。用PHP来生成一张图,然后传递给前端来做验证。
实现
本来PHP的图像代码我根本没有接触过,所以就去网上查了一下,结果发现原理还是蛮简单的。
先说原理吧,其实非常的简单。
1.先用PHP创建一个图,并加上背景颜色;
2.然后生成一串自己想要的随机字符,并画在之前创建好的图上;
3.加一些干扰线;
4.加一些噪点;
这样,一张随机码的图就做好了。下面上代码。
验证码生成页
<?php
session_start();
header('Content-type: image/png');
$img = imagecreate(150 ,40);
$bg = imagecolorallocate($img,rand(50,200),rand(0,155),rand(0,155));
$fontColor = imageColorAllocate( $img, 255, 255, 255);
$fontStyle = 'ROCK.TTF';
$x = imagesx($img);
$y = imagesy($img);
$randLine = rand(5,10);
$randPoint = rand(0,250);
$allFont = '';
//填写随机字母
for($i=0; $i<4 ;$i++){
$rand = rand(1,3);
switch ($rand){
case 1://生成数字
$font = rand(48,57);
break;
case 2://生成大写字母
$font = rand(65,90);
break;
case 3://生成小写字母
$font = rand(97,122);
break;
}
$font = chr($font);
$randColor = imageColorAllocate( $img, rand(0,255), rand(0,255), rand(0,255));
imagefttext($img,25,rand(0,90),rand($x/4*$i+12,$x/4*($i+1)-12),rand(40,$y-25),$randColor,$fontStyle,$font);
$allFont .= $font;
}
$_SESSION['captcha'] = $allFont; //添加到session中以便验证
//添加噪点
while ($randPoint--){
$randColor = imageColorAllocate( $img, rand(0,255), rand(0,255), rand(0,255));
imagesetpixel($img,rand(0,$x),rand(0,$y),$randColor);
}
//添加横穿线
while($randLine--){
$randColor = imageColorAllocate( $img, rand(0,255), rand(0,255), rand(0,255));
imageLine($img,rand(0,$x),rand(0,$y),rand(0,$x),rand(0,$y),$randColor);
}
ImagePng($img);
ImageDestroy($img);
?>
用SESSION来记录生成出的编码,以便于后续验证。设置了http协议的头信息,告诉浏览器我这个文件是一个图片文件。然后设置一些图画的东西,颜色啊,字体啊。因为是生成验证图片,所以颜色都做成了随机生成的。然后用ASC码生成了一些随机的数字和字母组成的串。画在创建好的图像上。这里本来是有两个函数可以写到画板上的,分别是imagefttext和imagestring,但是后者有一个缺点,不能设置文字的大小,当然,他有一个字号,只有1到5.但是远远不能满足需求。我在网上找了一些也没有解决方法,唯一的解决方法就是用前面那个函数来代替。不过对于我来说都是一样的。后面就是加一些噪点和干扰线了。这个可以自由发挥,可以加一些图形,三角方块什么的,看个人喜好了。
验证码的图片生成好了,下面就开始用了。在之前写好的login.php 文件下增加一行代码
<span style="white-space:pre"> </span><tr>
<td>验证码:</td>
<td><img src = "captcha.php" onclick = "this.src = 'captcha.php?id='+Math.random();" alt = "点击更换验证码">看不清?点击更换图片</img></td>
<td><input type = "text" name = "captcha" /></td>
</tr>
captcha.php 是上面的验证码生成文件。然后设置一个点击更换的事件,这样就大功告成了~
最后,再写一个验证的判断语句就可以了
<span style="white-space:pre"> </span>if(strcasecmp( $_POST['captcha'], $_SESSION['captcha']) <> 0){
echo '验证码不正确';
exit();
}
这里忽略了两个及字符串的大小写,然后进行验证。
总结
本来刚解除这个画图的函数感觉挺好玩的。就多玩了两下,想做一个逆向分析器,结果发现PHP里面那个RGB解析函数实在是太坑了,不能解析出正确的RGB色彩值,而且感觉浪费了不少的时间,所以就先将这个东西封存吧。在做这个东西得过程中,感觉没什么难点,就是最后验证语句我直接用<>来判断了,结果大小写问题就出来了。
填坑
之前写的代码有两处坑,代码贴出去才发现这个问题,现在贴出来。
1.之前用javascript写的清空函数,其实在html直接用type = "reset"来代替;
2.之前的代码中注册页面的判空函数,取username空间的函数有个大小写错误,应该是getElementById。javascript是对大小写敏感的,我这个大小写错误的总是出现。