一、为什么要使用验证码?
在登录网站时,为了提高网站的安全性,屏蔽机器请求,避免用户”灌水“等行为,经常需要输入各种各样的验证码。一般服务端业务,写请求产生的消耗要远远大于读请求,对于能产生大量写请求的银器情况,我们都应当予以干预。通常情况下,验证码是图片中的一个字符串(数字或英文字母),用户需要识别其中的信息,才能正常登录。那么我们首先来了解一下验证码是什么。
二、验证码是什么?
验证码是自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计算机和人的全自动程序。
三、验证码的设计思路
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实现验证码的制作