php实现captcha点击刷新验证码

发布时间:2020-02-25编辑:脚本学堂
有关php captcha点击验证码的例了,php生成验证码的类,不同于以往传统的验证码,用于手机用户点击某一位置确认验证码,一起研究下。

php实现的click captcha点击验证码类与实例。

一、需求:
表单验证码,手机用户访问可以不用输入,而是click某一位置便可确认验证码。

二、原理:
1、使用PHP imagecreate创建PNG图象,在图中画N个圆弧,其中一个是完整的圆(验证用),将圆心坐标及半径记录入session。
2、在浏览器,当用户在验证码图片上点击时,记录点击的位置。
3、将用户点击的坐标与session记录的圆心坐标、半径比较,判断是否在圆中,如是则验证通过。

效果图:
php captcha点击刷新验证码

三、实现方法:
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 } ?>