以前輸出驗證碼的時候用過一個方法,在前臺用JS生成驗證碼字符串,再傳遞到後臺用PHP輸出驗證碼圖像。這樣在驗證時就不需要使用$_SESSION傳遞驗證碼的值,直接用JS比較生成的字符串和輸入的字符串是否相等即可。
但是這種方法的缺點是結構化編程比較明顯,並且感覺脫節比較嚴重。在網上找了一些生成驗證碼的方法,也都不太完整,有些只包括生成圖像並沒有包括完整的驗證部分,因此在此給出完整的驗證碼生成類和驗證過程。
index.php
其中<img src="ValidationCode.class.php" id="checkImg">用於輸出驗證碼圖像。checkImg.οnclick=function() { checkImg.src="ValidationCode.class.php?num="+Math.random(); } 用於在單擊時重新加載圖像
<?php
session_start(); //用於在$_SESSION中獲取驗證碼的值
?>
<script type="text/javascript">
window.οnlοad=function() {
var xmlHttp = false;
if (window.XMLHttpRequest) { //Mozilla、Safari等瀏覽器
xmlHttp = new XMLHttpRequest();
}
else if (window.ActiveXObject) { //IE瀏覽器
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
var checkImg=document.getElementById("checkImg");
var checkCode=document.getElementById("checkCode");
checkImg.οnclick=function() {
checkImg.src="ValidationCode.class.php?num="+Math.random(); //以下用於單擊驗證碼時重新加載驗證碼圖片
//需要加num=Math.random()以防止圖片在本地緩存,單擊圖片時不刷新顯示
}
checkCode.οnblur=function(){
//alert("Hello");
xmlHttp.open("POST","checkCode.php",true);
xmlHttp.onreadystatechange=function () {
if(xmlHttp.readyState==4 && xmlHttp.status==200) {
var msg=xmlHttp.responseText; //設置標誌用於表示驗證碼是否正確
if(msg=='1')
document.getElementById("checkResult").innerHTML="正確"; //在這可以設置其中間顯示一張圖片
else
document.getElementById("checkResult").innerHTML="錯誤";
}
}
xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlHttp.send("validateCode="+checkCode.value);
}
}
</script>
<input type="text" id="checkCode">
<img src="ValidationCode.class.php" id="checkImg"><span id="checkResult">請在此輸入驗證碼</span>
ValidationCode.class.php
驗證碼的生成類,要使用$_SESSION['checkCode']將驗證碼的值存入$_SESSION中。
<?php
session_start(); //爲了將驗證碼的值保留在$_SESSION中
class ValidationCode {
private $width;
private $height;
private $codeNum; //驗證碼的個數
private $image; //圖像資源
private $checkCode; //驗證碼字符串
function __construct($width=60,$height=20,$codeNum=4) {
$this->width=$width;
$this->height=$height;
$this->codeNum=$codeNum;
$this->checkCode=$this->createCheckCode();
}
//通過調用該方法向瀏覽器輸出驗證碼圖像
function showImage() {
$this->createImage(); //第一步:創建背景圖像
$this->setDisturbColor(); //第二步:設置干擾元素,此處只加了干擾直線
$this->outputText(); //第三步:輸出驗證碼
$this->outputImage(); //第四步:輸出圖像
}
//通過調用該方法獲取隨機創建的驗證碼字符串
function getCheckCode(){
return $this->checkCode;
}
//創建背景圖像
private function createImage(){
$this->image=imagecreatetruecolor($this->width, $this->height);
//隨機背景色
$backColor=imagecolorallocate($this->image, rand(225,255), rand(225,255), rand(225,255));
//爲背景填充顏色
imagefill($this->image, 0, 0, $backColor);
//設置邊框顏色
$border=imagecolorallocate($this->image, 0, 0, 0);
//畫出矩形邊框
imagerectangle($this->image, 0, 0, $this->width-1, $this->height-1, $border);
}
//輸出干擾元素
private function setDisturbColor() {
$lineNum=rand(2,4); //設置干擾線數量
for($i=0;$i<$lineNum;$i++) {
$x1=rand(0,$this->width/2);
$y1=rand(0,$this->height/2);
$x2=rand($this->width/2,$this->width);
$y2=rand($this->height/2,$this->height);
$color=imagecolorallocate($this->image, rand(100,200), rand(100,200), rand(100,200)); //顏色設置比背景深,比文字淺
imageline($this->image, $x1, $y1, $x2, $y2, $color);
}
}
//生成驗證碼字符串
private function createCheckCode() { //或者這裏可以通過前臺傳遞過來的參數生成字符
$code="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$string="";
for($i=0;$i<$this->codeNum;$i++) {
$char=$code{rand(0,strlen($code)-1)};
$string.=$char;
}
return $string;
}
//輸出驗證碼
private function outputText() {
//echo "<script type='text/javascript'>alert('".$this->checkCode."')</script>";
$string=$this->checkCode;
for($i=0;$i<$this->codeNum;$i++) {
$x=rand(1,4)+$this->width*$i/$this->codeNum;
$y=rand(1,$this->height/4);
$color=imagecolorallocate($this->image, rand(0,128), rand(0,128), rand(0,128));
$fontSize=rand(4,5);
imagestring($this->image, $fontSize, $x, $y, $string[$i], $color);
}
}
//輸出圖像
private function outputImage() {
if(imagetypes() & IMG_GIF) {
header("Content-type:image/gif");
imagepng($this->image);
}else if(imagetypes() & IMG_JPG) {
header("Content-type:image/jpeg");
imagepng($this->image);
}else if(imagetypes() & IMG_PNG) {
header("Content-type:image/png");
imagepng($this->image);
}else if(imagetypes() & IMG_WBMP) {
header("Content-type:image/vnd.wap.wbmp");
imagepng($this->image);
}else {
die("PHP不支持圖像創建");
}
}
function __destruct() {
imagedestroy($this->image);
}
}
$code=new ValidationCode(60, 20, 4);
$_SESSION['checkCode']=$code->getCheckCode(); //將驗證碼的值存入session中以便在頁面中調用驗證
$code->showImage(); //輸出驗證碼
?>
checkCode.php
和index.php結合以驗證輸入的正確性,並用Ajax改變前端顯示
<?php
session_start();
//注意如此此處存在中文驗證碼時,用Ajax傳值要注意存在中文亂碼的問題
$validateCode=$_POST['validateCode'];
if(strtoupper($validateCode)==strtoupper($_SESSION['checkCode'])) //判斷文本框中輸入的值和$_SESSION中保存的驗證碼值是否相等
echo "1";
else
echo "0";
?>