簡單的驗證碼機制

 Mon, 24 Jul 2006 11:17:30 +0800

為了自己網站改版,隨手寫了一個留言板。並且想了一個簡單的驗證碼機制,防止他人使用機器人在我的留言板亂倒東西。

由於是使用php,所以有一些方便的工具(GD、Session),可以整合出完整的功能。

我的想法如下:

  1. 驗證碼(check_code)存放在資料庫,用一個check_id作為key
  2. 留言板的留言與看留言的介面在同一個頁面,每次進入這個頁面時,驗證碼都要更換。所以不能直接使用session_id作為key
  3. 每次進入頁面時,會刪除舊的check_id,產生新的check_id,同時產生一組check_code存放在資料庫
  4. 用gd產生check_code的圖片,在輸入留言的form上面顯示
  5. 程式之間利用session來取得check_id,check_code不會在client端出現,所以可以確保一些安全性

以下簡述一下我的程式:

第一步還是要在資料庫中建立一個資料表(我用的是mysql),我取名叫做fsession:

CREATE TABLE `fsession` (
`check_id` varchar(40) NOT NULL default '',
`check_code` varchar(8) NOT NULL default '00000000',
PRIMARY KEY  (`check_id`)
) TYPE=MyISAM;

接下來是產生check_id的code:

session_start();
$sql = sprintf("SELECT * FROM fsession WHERE check_id='%s'", $_SESSION['check_id']);
$result = $db->query($sql);
$tmp = $db->num_rows($result);
if ($tmp > 0) {//如果有舊的check_id,就把他從資料庫刪掉
$sql = sprintf("DELETE FROM fsession WHERE check_id='%s'", $_SESSION['check_id']);
$db->query($sql);
}
//接下來產生新的check_id以及check_code
$_SESSION['check_id'] = md5(time().rand());
//上面產生check_id
$sql = sprintf("INSERT INTO fsession (check_id, check_code) VALUES ('%s', '%s')", $_SESSION['checkid'], mt_rand(10000000,99999999));
//上面產生一組八位數的check_code
$db->query($sql);
//ok,存入資料庫

(這個方法不太好,因為我也不太確定不同字串產生的md5摘要是否會一樣.....不過因為摘要長度是一樣的,比較方便,所以先用了:D。也許應該用auto_increment的id比較好?只要改一下程式就可以了(先存入資料庫再取得check_id,但是check_id的type要改成int))

接下來是產生驗證碼圖片的程式(使用GD,幾乎從php manual上面的例子照抄....):

session_start();
if (!empty($_SESSION['check_id'])) {
$sql = sprintf("SELECT check_code FROM fsession WHERE check_id='%s'", $_SESSION['check_id']);
$result = $db->query($sql);
if ($db->num_rows($result) == 0) {
$code = "error! db";
} else {
list($code) = $db->fetch_row($result);
}
} else {
$code = "error! session";
}
header("Content-type: image/jpeg");
//指定輸出內容的type
$im = imagecreatefromjpeg("images/code_bg.jpg");
//用一張背景圖產生需要的背景
$color = imagecolorallocate($im, 32, 32, 32);
//指定顏色
imagettftext($im, 12, 0, 2, 13, $color, "fonts/georgiai.ttf",$code);
//利用true type字型來產生圖片
imagejpeg($im);
//輸出所產生的圖片內容到瀏覽器
imagedestroy($im);

假設這一隻程式叫做authcode.php,只要在需要圖片的地方使用<img src="authcode.php">就可以顯示圖片。另外,字型檔案與字型大小需要依照系統做調整(也可以用ps、type1等字型,尤其是在linux系統上)

最後,只要在留言存入資料庫的地方,先檢查使用者輸入的檢查碼,與存在資料庫中的檢查碼比對,就可以確認。