**需求:**
現在常用的表單驗證碼大部分都是要用戶輸入為主,但這樣對手機用戶會不方便。
如果手機用戶訪問,可以不用輸入,而是click某一位置便可確認驗證碼,這樣就會方便很多。
原理:
1.使用PHP?imagecreate創建PNG圖象,在圖中畫N個圓弧,其中一個是完整的圓(驗證用),將圓心坐標及半徑記錄入session。
2.在瀏覽器,當用戶在驗證碼圖片上點擊時,記錄點擊的位置。
3.將用戶點擊的坐標與session記錄的圓心坐標、半徑比較,判斷是否在圓中,如是則驗證通過。

**ClickCaptcha.class.php**
~~~
<?php
/**Click Captcha 驗證碼類
*Date: 2013-05-04
*Author: fdipzone
*Ver: 1.0
*/
class ClickCaptcha { // class start
public $sess_name = 'm_captcha';
public $width = 500;
public $height = 200;
public $icon = 5;
public $iconColor = array(255, 255, 0);
public $backgroundColor = array(0, 0, 0);
public $iconSize = 56;
private $_img_res = null;
? public function __construct($sess_name=''){
? ? ? if(session_id() == ''){
? ? ? ? ? session_start();
? ? ? }
? ? ? if($sess_name!=''){
? ? ? ? ? $this->sess_name = $sess_name; // 設置session name
? ? ? }
? }
/**創建驗證碼 */
public function create(){
// 創建圖象
$this->_img_res = imagecreate($this->width, $this->height);
// 填充背景
ImageColorAllocate($this->_img_res, $this->backgroundColor[0], $this->backgroundColor[1], $this->backgroundColor[2]);
// 分配顏色
$col_ellipse = imagecolorallocate($this->_img_res, $this->iconColor[0], $this->iconColor[1], $this->iconColor[2]);
$minArea = $this->iconSize/2+3;
// 混淆用圖象,不完整的圓
for($i=0; $i<$this->icon; $i++){
$x = mt_rand($minArea, $this->width-$minArea);
$y = mt_rand($minArea, $this->height-$minArea);
$s = mt_rand(0, 360);
$e = $s + 330;
imagearc($this->_img_res, $x, $y, $this->iconSize, $this->iconSize, $s, $e, $col_ellipse);
}
// 驗證用圖象,完整的圓
$x = mt_rand($minArea, $this->width-$minArea);
$y = mt_rand($minArea, $this->height-$minArea);
$r = $this->iconSize/2;
imagearc($this->_img_res, $x, $y, $this->iconSize, $this->iconSize, 0, 360, $col_ellipse);
// 記錄圓心坐標及半徑
$this->captcha_session($this->sess_name, array($x, $y, $r));
// 生成圖象
Header("Content-type: image/PNG");
ImagePNG($this->_img_res);
ImageDestroy($this->_img_res);
exit();
}
/**檢查驗證碼
* @param String $captcha 驗證碼
* @param int $flag 驗證成功后 0:不清除session 1:清除session
* @return boolean
*/
public function check($captcha, $flag=1){
if(trim($captcha)==''){
return false;
}
if(!is_array($this->captcha_session($this->sess_name))){
return false;
}
list($px, $py) = explode(',', $captcha);
list($cx, $cy, $cr) = $this->captcha_session($this->sess_name);
if(isset($px) && is_numeric($px) && isset($py) && is_numeric($py) &&
isset($cx) && is_numeric($cx) && isset($cy) && is_numeric($cy) && isset($cr) && is_numeric($cr)){
if($this->pointInArea($px,$py,$cx,$cy,$cr)){
if($flag==1){
$this->captcha_session($this->sess_name,'');
}
return true;
}
}
return false;
}
/**判斷點是否在圓中
* @param int $px 點x
* @param int $py 點y
* @param int $cx 圓心x
* @param int $cy 圓心y
* @param int $cr 圓半徑
* sqrt(x^2+y^2)<r
*/
private function pointInArea($px, $py, $cx, $cy, $cr){
$x = $cx-$px;
$y = $cy-$py;
return round(sqrt($x*$x + $y*$y))<$cr;
}
/**驗證碼session處理方法
* @param String $name captcha session name
* @param String $value
* @return String
*/
private function captcha_session($name,$value=null){
if(isset($value)){
if($value!==''){
$_SESSION[$name] = $value;
}else{
unset($_SESSION[$name]);
}
}else{
return isset($_SESSION[$name])? $_SESSION[$name] : '';
}
}
} // class end
?>
~~~
**demo.php**
~~~
<?php
session_start();
require('ClickCaptcha.class.php');
if(isset($_GET['get_captcha'])){ // get captcha
$obj = new ClickCaptcha();
$obj->create();
exit();
}
if(isset($_POST['send']) && $_POST['send']=='true'){ // submit
$name = isset($_POST['name'])? trim($_POST['name']) : '';
$captcha = isset($_POST['captcha'])? trim($_POST['captcha']) : '';
$obj = new ClickCaptcha();
if($obj->check($captcha)){
echo 'your name is:'.$name;
}else{
echo 'captcha not match';
}
echo ' <a href="demo.php">back</a>';
}else{ // html
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title> Click Captcha Demo </title>
<script type="text/javascript" src="jquery-1.6.2.min.js"></script>
<script type="text/javascript">
$(function(){
$('#captcha_img').click(function(e){
var x = e.pageX - $(this).offset().left;
var y = e.pageY - $(this).offset().top;
$('#captcha').val(x+','+y);
})
$('#btn').click(function(e){
if($.trim($('#name').val())==''){
alert('Please input name!');
return false;
}
if($.trim($('#captcha').val())==''){
alert('Please click captcha!');
return false;
}
$('#form1')[0].submit();
})
})
</script>
</head>
<body>
<form name="form1" id="form1" method="post" action="demo.php" onsubmit="return false">
<p>name:<input type="text" name="name" id="name"></p>
<p>Captcha:Please click full circle<br><img id="captcha_img" src="demo.php?get_captcha=1&t=<?=time() ?>" style="cursor:pointer"></p>
<p><input type="submit" id="btn" value="submit"></p>
<input type="hidden" name="send" value="true">
<input type="hidden" name="captcha" id="captcha">
</form>
</body>
</html>
<?php } ?>
~~~
源碼下載:[點擊下載](http://download.csdn.net/detail/fdipzone/5331511)
- 前言
- php Captcha 驗證碼類
- php 替換敏感字符串
- php返回數據格式化類
- php XML文件解釋類
- php CSS Update Class
- PHPMailer - PHP email transport class
- PHP 遍歷文件夾及文件類及處理類
- 自動登入google play下載app report
- php click captcha 驗證碼類
- php 獲取頁面中的指定內容類
- php 支持斷點續傳的文件下載類
- php 縮略圖生成類,支持imagemagick及gd庫兩種處理
- php 根據url自動生成縮略圖
- php 過濾html標記屬性類
- php HTTP請求類,支持GET,POST,Multipart/form-data
- php Cookies 操作類
- php 密碼生成類
- php main 與 iframe 相互通訊類(同域/跨域)
- php 根據url自動生成縮略圖,并處理高并發問題
- php Timer 頁面運行時間監測類
- php 雙向隊列類
- php 導出CSV抽象類
- php zip文件內容比較類
- php 獲取/設置用戶訪問頁面語言類
- php 獲取Youtube某個User所有Video信息
- php 字符編碼轉換類,支持ANSI、Unicode、Unicode big endian、UTF-8、UTF-8+Bom 互相轉換
- php 版本處理類