既简单又安全的PHP验证码 附调用方法


Posted in PHP onJune 02, 2016

一、验证码示例

既简单又安全的PHP验证码 附调用方法

二、php验证码类,secoder.class.php

<?php 
/** 
 * 安全验证码 
 * 
 * 安全的验证码要:验证码文字扭曲、旋转,使用不同字体,添加干扰码 
 * 
 * @author 流水孟春 <cmpan(at)qq.com> 
 * @link http://labs.yulans.cn/YL_Security_Secoder 
 * @link http://wiki.yulans.cn/docs/yl/security/secoder 
 */ 
class YL_Security_Secoder { 
  /** 
   * 验证码的session的下标 
   * 
   * @var string 
   */ 
  //public static $seKey = 'sid.sek ey.ylans.cn'; 
  public static $seKey = 'sid'; 
  public static $expire = 3000;   // 验证码过期时间(s) 
  /** 
   * 验证码中使用的字符,01IO容易混淆,建议不用 
   * 
   * @var string 
   */ 
  public static $codeSet = '346789ABCDEFGHJKLMNPQRTUVWXY'; 
  public static $fontSize = 25;   // 验证码字体大小(px) 
  public static $useCurve = true;  // 是否画混淆曲线 
  public static $useNoise = true;  // 是否添加杂点  
  public static $imageH = 0;    // 验证码图片宽 
  public static $imageL = 0;    // 验证码图片长 
  public static $length = 4;    // 验证码位数 
  public static $bg = array(243, 251, 254); // 背景 
   
  protected static $_image = null;   // 验证码图片实例 
  protected static $_color = null;   // 验证码字体颜色 
   
  /** 
   * 输出验证码并把验证码的值保存的session中 
   * 验证码保存到session的格式为: $_SESSION[self::$seKey] = array('code' => '验证码值', 'time' => '验证码创建时间'); 
   */ 
  public static function entry() { 
    // 图片宽(px) 
    self::$imageL || self::$imageL = self::$length * self::$fontSize * 1.5 + self::$fontSize*1.5;  
    // 图片高(px) 
    self::$imageH || self::$imageH = self::$fontSize * 2; 
    // 建立一幅 self::$imageL x self::$imageH 的图像 
    self::$_image = imagecreate(self::$imageL, self::$imageH);  
    // 设置背景    
    imagecolorallocate(self::$_image, self::$bg[0], self::$bg[1], self::$bg[2]);  
    // 验证码字体随机颜色 
    self::$_color = imagecolorallocate(self::$_image, mt_rand(1,120), mt_rand(1,120), mt_rand(1,120)); 
    // 验证码使用随机字体  
    //$ttf = dirname(__FILE__) . '/ttfs/' . mt_rand(1, 20) . '.ttf'; 4 
    $ttf = dirname(__FILE__) . '/ttfs/4.ttf';  
     
    if (self::$useNoise) { 
      // 绘杂点 
      self::_writeNoise(); 
    }  
    if (self::$useCurve) { 
      // 绘干扰线 
      self::_writeCurve(); 
    } 
     
    // 绘验证码 
    $code = array(); // 验证码 
    $codeNX = 0; // 验证码第N个字符的左边距 
    for ($i = 0; $i<self::$length; $i++) { 
      $code[$i] = self::$codeSet[mt_rand(0, 27)]; 
      $codeNX += mt_rand(self::$fontSize*1.2, self::$fontSize*1.6); 
      // 写一个验证码字符 
      imagettftext(self::$_image, self::$fontSize, mt_rand(-40, 70), $codeNX, self::$fontSize*1.5, self::$_color, $ttf, $code[$i]); 
    } 
     
    // 保存验证码 
    isset($_SESSION) || session_start(); 
    $_SESSION[self::$seKey]['code'] = join('', $code); // 把校验码保存到session 
    $_SESSION[self::$seKey]['time'] = time(); // 验证码创建时间 
         
    header('Cache-Control: private, max-age=0, no-store, no-cache, must-revalidate'); 
    header('Cache-Control: post-check=0, pre-check=0', false);    
    header('Pragma: no-cache');    
    header("content-type: image/png"); 
   
    // 输出图像 
    imagepng(self::$_image);  
    imagedestroy(self::$_image); 
  } 
   
  /** 
   * 画一条由两条连在一起构成的随机正弦函数曲线作干扰线(你可以改成更帅的曲线函数) 
   *    
   *   高中的数学公式咋都忘了涅,写出来 
   *   正弦型函数解析式:y=Asin(ωx+φ)+b 
   *   各常数值对函数图像的影响: 
   *    A:决定峰值(即纵向拉伸压缩的倍数) 
   *    b:表示波形在Y轴的位置关系或纵向移动距离(上加下减) 
   *    φ:决定波形与X轴位置关系或横向移动距离(左加右减) 
   *    ω:决定周期(最小正周期T=2π/?ω?) 
   * 
   */ 
  protected static function _writeCurve() { 
    $A = mt_rand(1, self::$imageH/2);         // 振幅 
    $b = mt_rand(-self::$imageH/4, self::$imageH/4);  // Y轴方向偏移量 
    $f = mt_rand(-self::$imageH/4, self::$imageH/4);  // X轴方向偏移量 
    $T = mt_rand(self::$imageH*1.5, self::$imageL*2); // 周期 
    $w = (2* M_PI)/$T; 
             
    $px1 = 0; // 曲线横坐标起始位置 
    $px2 = mt_rand(self::$imageL/2, self::$imageL * 0.667); // 曲线横坐标结束位置       
    for ($px=$px1; $px<=$px2; $px=$px+ 0.9) { 
      if ($w!=0) { 
        $py = $A * sin($w*$px + $f)+ $b + self::$imageH/2; // y = Asin(ωx+φ) + b 
        $i = (int) ((self::$fontSize - 6)/4); 
        while ($i > 0) {  
          imagesetpixel(self::$_image, $px + $i, $py + $i, self::$_color); // 这里画像素点比imagettftext和imagestring性能要好很多          
          $i--; 
        } 
      } 
    } 
     
    $A = mt_rand(1, self::$imageH/2);         // 振幅     
    $f = mt_rand(-self::$imageH/4, self::$imageH/4);  // X轴方向偏移量 
    $T = mt_rand(self::$imageH*1.5, self::$imageL*2); // 周期 
    $w = (2* M_PI)/$T;    
    $b = $py - $A * sin($w*$px + $f) - self::$imageH/2; 
    $px1 = $px2; 
    $px2 = self::$imageL; 
    for ($px=$px1; $px<=$px2; $px=$px+ 0.9) { 
      if ($w!=0) { 
        $py = $A * sin($w*$px + $f)+ $b + self::$imageH/2; // y = Asin(ωx+φ) + b 
        $i = (int) ((self::$fontSize - 8)/4); 
        while ($i > 0) {      
          imagesetpixel(self::$_image, $px + $i, $py + $i, self::$_color); // 这里(while)循环画像素点比imagettftext和imagestring用字体大小一次画出(不用这while循环)性能要好很多   
          $i--; 
        } 
      } 
    } 
  } 
   
  /** 
   * 画杂点 
   * 往图片上写不同颜色的字母或数字 
   */ 
  protected static function _writeNoise() { 
    for($i = 0; $i < 10; $i++){ 
      //杂点颜色 
      $noiseColor = imagecolorallocate( 
               self::$_image,  
               mt_rand(150,225),  
               mt_rand(150,225),  
               mt_rand(150,225) 
             ); 
      for($j = 0; $j < 5; $j++) { 
        // 绘杂点 
        imagestring( 
          self::$_image, 
          5,  
          mt_rand(-10, self::$imageL),  
          mt_rand(-10, self::$imageH),  
          self::$codeSet[mt_rand(0, 27)], // 杂点文本为随机的字母或数字 
          $noiseColor 
        ); 
      } 
    } 
  } 
   
  /** 
   * 验证验证码是否正确 
   * 
   * @param string $code 用户验证码 
   * @param bool 用户验证码是否正确 
   */ 
  public static function check($code) { 
    isset($_SESSION) || session_start(); 
    // 验证码不能为空 
    if(empty($code) || empty($_SESSION[self::$seKey])) { 
      //echo $_SESSION[self::$seKey]['code'].'1'; 
      return false; 
           
    } 
    // session 过期 
    if(time() - $_SESSION[self::$seKey]['time'] > self::$expire) { 
      unset($_SESSION[self::$seKey]); 
      //echo $_SESSION[self::$seKey]['code'].'2'; 
      return false; 
      //return 0; 
    } 
 
//   if($code == $_SESSION[self::$seKey]['code']) { 
    if(strtoupper($code) == $_SESSION[self::$seKey]['code']) { //不区分大小写比较 
      //echo $_SESSION[self::$seKey]['code'].'3'; 
      return true;     
    } 
    //echo $_SESSION[self::$seKey]['code'].'4'; 
    return false; 
         
  } 
} 
 
 
// useage 
/* 
YL_Security_Secoder::$useNoise = false; // 要更安全的话改成true 
YL_Security_Secoder::$useCurve = true; 
YL_Security_Secoder::entry(); 
*/ 
 
/* 
// 验证验证码 
if (!YL_Security_Secoder::check(@$_POST['secode'])) { 
  print 'error secode'; 
} 
*/

三、调用方法

1、显示验证码页面code.php

<?php  
  session_start(); 
  require 'secoder.class.php'; //先把类包含进来,实际路径根据实际情况进行修改。  
  $vcode = new YL_Security_Secoder();   //实例化一个对象  
  $vcode->entry();  
?>

2、检查验证码是否正确

<?php  
  session_start(); 
  require 'secoder.class.php'; //先把类包含进来,实际路径根据实际情况进行修改。  
  $vcode = new YL_Security_Secoder();   //实例化一个对象  
  //$vcode->entry();  
  $code = $_GET['code'];  
  echo $vcode->check($code);     
  //$_SESSION['code'] = $vc->getCode();//验证码保存到SESSION中 
?>

3、验证码输入框调用页面

<img id="messageImg" src='images/tishis2.gif' width='16' height='16'> 单击图片重新获取验证码<br> 
<a href="#"><img src="code.php" onclick="javascript:this.src='code.php?tm='+Math.random();" />

以上就是本文的全部内容,希望对大家学习PHP程序设计有所帮助。

PHP 相关文章推荐
PHP+XML 制作简单的留言本 图文教程
Nov 02 PHP
真正根据utf8编码的规律来进行截取字符串的函数(utf8版sub_str )
Oct 24 PHP
解析centos中Apache、php、mysql 默认安装路径
Jun 25 PHP
PHP仿博客园 个人博客(2) 数据库增添改删
Jul 05 PHP
PHP积分兑换接口实例
Feb 09 PHP
新浪微博OAuth认证和储存的主要过程详解
Mar 27 PHP
使用PHP如何实现高效安全的ftp服务器(二)
Dec 30 PHP
PHP获取指定时间段之间的 年,月,天,时,分,秒
Jun 05 PHP
php中的登陆login实例代码
Jun 20 PHP
解决Yii2邮件发送结果返回成功,但接收不到邮件的问题
May 23 PHP
win10 apache配置虚拟主机后localhost无法使用的解决方法
Jan 27 PHP
PHP操作MongoDB实现增删改查功能【附php7操作MongoDB方法】
Apr 24 PHP
yii2分页之实现跳转到具体某页的实例代码
Jun 02 #PHP
[原创]php实现子字符串位置相互对调互换的方法
Jun 02 #PHP
PHP处理数组和XML之间的互相转换
Jun 02 #PHP
PHP邮箱验证示例教程
Jun 01 #PHP
PHP微信公众号自动发送红包API
Jun 01 #PHP
PHP模块化安装教程
Jun 01 #PHP
深入理解PHP之源码目录结构与功能说明
Jun 01 #PHP
You might like
虫族 ZERG 概述
2020/03/14 星际争霸
php GD绘制24小时柱状图
2008/06/28 PHP
PHP批量生成缩略图的代码
2008/07/19 PHP
PHP 各种排序算法实现代码
2009/08/20 PHP
php在线代理转向代码
2012/05/05 PHP
php实现微信发红包
2015/12/05 PHP
新闻内页-JS分页
2006/06/07 Javascript
关于jQuery的inArray 方法介绍
2011/10/08 Javascript
jquery仿QQ商城带左右按钮控制焦点图片切换滚动效果
2013/06/27 Javascript
使用javascript过滤html的字符串(注释标记法)
2013/07/08 Javascript
jquery 通过name快速取值示例
2014/01/24 Javascript
JavaScript 开发工具webstrom使用指南
2014/12/09 Javascript
代码分析jQuery四种静态方法使用
2015/07/23 Javascript
深入理解JS DOM事件机制
2016/08/06 Javascript
微信公众平台开发教程(六)获取个性二维码的实例
2016/12/02 Javascript
jQuery实现的简单悬浮层功能完整实例
2017/01/23 Javascript
vuejs指令详解
2017/02/07 Javascript
JS实现动态修改table及合并单元格的方法示例
2017/02/20 Javascript
Angular.JS中的指令引用template与指令当做属性详解
2017/03/30 Javascript
vue二级路由设置方法
2018/02/09 Javascript
Vue2.0学习系列之项目上线的方法步骤(图文)
2018/09/25 Javascript
Vue自定义指令上报Google Analytics事件统计的方法
2019/02/25 Javascript
Vue+ElementUI使用vue-pdf实现预览功能
2019/11/26 Javascript
你不知道的 TypeScript 高级类型(小结)
2020/08/28 Javascript
python 美化输出信息的实例
2018/10/15 Python
Python 读取xml数据,cv2裁剪图片实例
2020/03/10 Python
Python之字符串的遍历的4种方式
2020/12/08 Python
入党积极分子介绍信
2014/01/17 职场文书
计算机应届毕业生自荐信范文
2014/02/23 职场文书
快餐公司创业计划书
2014/04/29 职场文书
工会趣味活动方案
2014/08/18 职场文书
搞笑的爱情检讨书
2014/10/01 职场文书
个人贷款授权委托书样本
2014/10/07 职场文书
教师见习报告范文
2014/11/03 职场文书
离婚代理词范文
2015/05/23 职场文书
中学音乐课教学反思
2016/02/18 职场文书