PHP实现验证码的制作与校验

8 篇文章 0 订阅
6 篇文章 0 订阅
一、为什么要使用验证码?

    在登录网站时,为了提高网站的安全性,屏蔽机器请求,避免用户”灌水“等行为,经常需要输入各种各样的验证码。一般服务端业务,写请求产生的消耗要远远大于读请求,对于能产生大量写请求的银器情况,我们都应当予以干预。通常情况下,验证码是图片中的一个字符串(数字或英文字母),用户需要识别其中的信息,才能正常登录。那么我们首先来了解一下验证码是什么。

二、验证码是什么?

    验证码是自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计算机和人的全自动程序。

三、验证码的设计思路

    1)编写HTML页面,在页面中创建一个表单,用于输入用户登录信息和验证码;
    2)使用PHP提供的图像技术生成验证码;
    3)利用尝过的Session技术验证用户提交的验证码;
    4)使用JavaScript技术在不刷新页面的情况下,更换验证码,优化用户体验;



四、验证码的制作与校验实现

1、编写HTML页面,在页面中创建一个表单,用于输入用户登录信息和验证码;

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>管理员登录</title>
</head>
<body>
    <form method="post">
        <table>
            <tr><td>用户名:</td><td><input type="text" name="admin_name" placeholer="请输入用户名……"/></td></tr>
            <tr><td>密   码:</td><td><input type="password" name="admin_pwd" /></td></tr>
            <tr><td>验证码:</td><td><input type='text' name='check' id='icode' value=''/><span id='checkcode'></span></td></tr>
            <tr><td><img id='captch' border='1' src="__CONTROLLER__/image?r=<?php echo rand();?>" width='100' heigth='30'/></td>
            <td><a href='javascript:void(0)' οnclick="document.getElementById('captch').src='__CONTROLLER__/image?r='+Math.random()">看不清?</a></td></tr>
            <tr><td><input type="reset" value="取消" /></td><td><input type="submit" value="登录" /></td></tr>
        </table>
    </form>
    <script>
//下面是使用Ajax实现与服务端的异步交互
 document.getElementById("icode").οnblur=function(){
    if(window.XMLHttpRequest){
        request = new XMLHttpRequest();    //IE7+,Firefox,Chrome……
     }else{
        request = new ActiveXObject("Microsoft.XMLHTTP");//IE5、IE6或更早的版本
     }
     var url="check?check="+document.getElementById("icode").value;
    request.open('GET',url,true);
    request.send();
    request.onreadystatechange = function() {
        if (request.readyState===4) {
            if (request.status===200) { 
                document.getElementById("checkcode").innerHTML = request.responseText;//XMLHttpRequest对象的responseText属性
            } else {
                alert("发生错误:" + request.status);
            }
        } 
    }        
}
</script>
</body>
</html>

Ajax实现验证码异步交互的PHP代码为:
if(IS_GET){
			if(isset($_REQUEST['check'])){
				session_start();
				//将用户输入的验证码与服务端存储的验证码内容进行对比
				if(strtolower($_REQUEST['check']) == strtolower($_SESSION['captch_code'])){
					echo '输入正确!';
				}else{
					echo '验证码错误!';
				}
			}
		
		}


2、使用PHP提供的图像技术生成验证码;

1)生成底图;(底图的产生并添加干扰元素)
    需要依赖PHP图片处理库GD,详细查看: http://php.net/gd
    查看是否支持GD,使用phpinfo()
2)生成验证内容;(生成无规律内容并保存在服务端)
    简单的随机数生成,使用PHP函数mt_rand();
    随机数字+字母生成,需要ASC||码理论基础;
    随机中文内容生成,需要UTF-8编码理论基础;
3)生成验证码图片;(将底图与验证内容合成一张图片)
    需要PHP操作SESSION基础;
4)对比校验验证码内容;(将用户输入与保存在服务端的验证内容进行对比)
    需要Ajax基础;

实战:
    生成底图
    生成100*30像素的底图     实现方法:imagecreatetruecolor(int $width,int $height)
    注意:该方法默认输出为黑色背景,输出图片前,必须提前输出图片header信息;

    添加验证码,即在底图上显示随机数字,控制好字体大小与分布,避免字体重叠或显示不全
    实现方法:int imagecolorallocate(resource $image,int $red,int $green,int $blue)
                     bool imagestring(resource $image,int $font,int $x,int $y,string $s,int $col)

纯数字验证码内容:
for($i=0;$i<4;$i++){
    $fontsize = 6;
    $fontcolor = imagecolorallocate($image,rand(0,120),rand(0,120),rand(0,120));//验证码颜色深
    $fontcontent = rand(0,9);
    $x = ($i*100/4)+rand(5,10);
    $y = rand(5,10);//设置验证码位置
    imagestring($image,$fontsize,$x,$y,$fontcontent,$fontcolor);
}

数字加大小写字母验证码内容:
for($i=0;$i<4;$i++){
    $fontsize = 6;
    $fontcolor = imagecolorallocate($image,rand(0,100),rand(0,100),rand(0,100));//验证码颜色深
    $data = 'abcdefghijkmnpqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXYZ123456789';
    $fontcontent = substr($data,rand(0,strlen($data)-1),1);//从$data对象中随机获取一个字符
    $captch_code .= $fontcontent;
    $x = ($i*100/4)+rand(5,10);
    $y = rand(5,15);//设置验证码位置
    imagestring($image,$fontsize,$x,$y,$fontcontent,$fontcolor);
}

添加干扰元素,干扰的点或线,一定要控制好颜色,避免”喧宾夺主“,影响识别验证码
    实现方法:bool imagesetpixel(resource $image,int $x,int $y,int $color)
                     bool imageline(resource $image,int $x1,int y1,int $x2,int $y2,int $color)

<span style="font-size:12px;">for($i<0;$i<200;$i++){
    //增加干扰点
    $pointcolor = imagecolorallocate($image,rand(50,200),rand(50,200),rand(50,200));//干扰点颜色浅
    imagesetpixel($image,rand(1,99),rand(1,29),$pointcolor);
}

for($i=0;$i<4;$i++){
    //增加干扰线
    $linecolor = imagecolorallocate($image,rand(90,200),rand(90,200),rand(90,200));//干扰线颜色更浅
    imageline($image,rand(1,99),rand(1,29),rand(1,99),rand(1,29),$linecolor);
}</span>
制作验证码的完整代码如下:
<?php
session_start();//必须处于程序顶部
$width = 100;
$height = 30;
$image = imagecreatetruecolor($width,$height);   //生成100*30的底图
$black = imagecolorallocate($image,0,0,0);//黑色
$bgcolor = imagecolorallocate($image,255,255,255);//write
imagefill($image,0,0,$bgcolor);//填充背景

$captch_code = "";//用于记录验证码内容
//生成4位随机验证码内容
for($i=0;$i<4;$i++){
    $fontsize = 6;
    $fontcolor = imagecolorallocate($image,rand(0,100),rand(0,100),rand(0,100));//验证码颜色深
    $data = 'abcdefghijkmnpqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXYZ123456789';
    $fontcontent = substr($data,rand(0,strlen($data)-1),1);//从$data对象中随机获取一个字符
    $captch_code .= $fontcontent;
    $x = ($i*100/4)+rand(5,10);
    $y = rand(5,15);//设置验证码位置
    imagestring($image,$fontsize,$x,$y,$fontcontent,$fontcolor);
}
$_SESSION['captch_code'] = $captch_code;

for($i<0;$i<200;$i++){
    //增加干扰点
    $pointcolor = imagecolorallocate($image,rand(50,200),rand(50,200),rand(50,200));//干扰点颜色浅
    imagesetpixel($image,rand(1,$width-1),rand(1,$height-1),$pointcolor);
}

for($i=0;$i<3;$i++){
    //增加干扰线
    $linecolor = imagecolorallocate($image,rand(100,200),rand(100,200),rand(100,200));//干扰线颜色更浅
    imageline($image,rand(1,$width-1),rand(1,$height-1),rand(1,$width-1),rand(1,$height-1),$linecolor);
}

header('Content-Type:image/png');
imagepng($image);//输出图像
//end销毁图片
imagedestroy($image);
?


 3、使用JavaScript技术在不刷新页面的情况下,更换验证码,优化用户体验;

由于验证码存在干扰信息与随机性,正常人也可能无法阅读,所以需要动态更换验证码:如增加”看不清“,”换一个“等链接可以更换看不清的验证码;
实现方法:1)增加可点击的”看不清“文字;
    2)用JS选取器选取验证码图片;
    3)用JS修改验证码图片地址;

2、通过SESSION存储验证码内容,即在服务端记录验证码信息,使用用户输入后做校验;多服务器情况下需要考虑集中管理session信息;
    实现方法:bool session_start(void)      必须处于佳酿最顶部;


4、将已生成的验证码提供给用户,并校验用户输入的验证码的正确性

这是在thinkphp中的校验代码:
if (IS_POST){
			$admin = M("admin");
			$adminInfo = $admin -> create();//获取通过POST方式得到的表示信息
			$where = array('admin_name' => $adminInfo["admin_name"]);
			$checkcode = $_POST['check'];
			echo $checkcode;
			if(strtolower($checkcode) != strtolower($_SESSION['captch_code'])){
				$this->error("",0);
			}else 
			if ($realpwd = $admin->where($where)->getField("admin_pwd")){
				if ($realpwd == md5($adminInfo["admin_pwd"])){
					session('admin_name',$adminInfo['admin_name']);
					$this->success("登录成功!",U('Student/showMajor'));//跳转到Student控制器下的show方法
					//验证完用户名和密码后,跳转到其他界面
				}
			}
			$this->error("用户名或密码不正确,请重试!");
			return ;//回到刚才登录的界面
		}
		$this->display();

参考慕课网上的视频:PHP实现验证码的制作


  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值