一个简单安全的PHP验证码类 附调用方法


Posted in PHP onJune 24, 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部分常见问题总结
Mar 27 PHP
PHP 抓取网页图片并且另存为的实现代码
Mar 24 PHP
用PHP实现的四则运算表达式计算实现代码
Aug 02 PHP
PHP表单提交表单名称含有点号(.)则会被转化为下划线(_)
Dec 14 PHP
simplehtmldom Doc api帮助文档
Mar 26 PHP
PHP人民币金额数字转中文大写的函数代码
Feb 27 PHP
PHP实现获取客户端IP并获取IP信息
Mar 17 PHP
thinkPHP中钩子的使用方法实例分析
Nov 16 PHP
PHP多维数组指定多字段排序的示例代码
May 16 PHP
php框架CodeIgniter主从数据库配置方法分析
May 25 PHP
实例讲解PHP验证邮箱是否合格
Jan 28 PHP
laravel-admin 实现在指定的相册下添加照片
Oct 21 PHP
java微信开发之上传下载多媒体文件
Jun 24 #PHP
微信公众号判断用户是否已关注php代码解析
Jun 24 #PHP
php微信开发之上传临时素材
Jun 24 #PHP
PHP微信开发之模板消息回复
Jun 24 #PHP
PHP微信开发之根据用户回复关键词\位置返回附近信息
Jun 24 #PHP
简单解析PHP程序的运行流程
Jun 23 #PHP
PHP微信开发之查询微信精选文章
Jun 23 #PHP
You might like
比较好用的PHP防注入漏洞过滤函数代码
2012/04/11 PHP
ThinkPHP惯例配置文件详解
2014/07/14 PHP
php学习笔记之基础知识
2014/11/08 PHP
php微信公众账号开发之前五个坑(一)
2016/09/18 PHP
Js四则运算函数代码
2012/07/21 Javascript
jquery插件之信息弹出框showInfoDialog(成功/错误/警告/通知/背景遮罩)
2013/01/09 Javascript
JS去除数组重复值的五种不同方法
2013/09/06 Javascript
在jquery中combobox多选的不兼容问题总结
2013/12/24 Javascript
jquery表单验证框架提供的身份证验证方法(示例代码)
2013/12/27 Javascript
jQuery移除元素自动解绑事件实现思路及代码
2014/05/31 Javascript
JS中FRAME的操作问题实例分析
2014/10/21 Javascript
jQuery实现页面顶部显示的进度条效果完整实例
2015/12/09 Javascript
快速解决js中window.location.href不工作的问题
2016/11/02 Javascript
jQuery模拟下拉框选择对应菜单的内容
2017/03/07 Javascript
基于Bootstrap模态对话框只加载一次 remote 数据的解决方法
2017/07/09 Javascript
在axios中使用params传参的时候传入数组的方法
2018/09/25 Javascript
详解ESLint在Vue中的使用小结
2018/10/15 Javascript
利用Vue构造器创建Form组件的通用解决方法
2018/12/03 Javascript
Vue+Element UI+Lumen实现通用表格分页功能
2019/02/02 Javascript
微信小程序页面传多个参数跳转页面的实现方法
2019/05/17 Javascript
vue项目创建步骤及路由router
2020/01/14 Javascript
[01:57]2016完美“圣”典风云人物:国士无双专访
2016/12/04 DOTA
[01:03:13]VG vs Pain 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
举例讲解Django中数据模型访问外键值的方法
2015/07/21 Python
python实现外卖信息管理系统
2018/01/11 Python
python使用递归的方式建立二叉树
2019/07/03 Python
pandas DataFrame 警告(SettingWithCopyWarning)的解决
2019/07/23 Python
Python超越函数积分运算以及绘图实现代码
2019/11/20 Python
使用Python爬取弹出窗口信息的实例
2020/03/14 Python
html5实现九宫格抽奖可固定抽中某项奖品
2020/06/15 HTML / CSS
Tory Burch英国官方网站:美国时尚生活品牌
2017/12/06 全球购物
药品采购员岗位职责
2014/02/08 职场文书
党员创先争优承诺书
2014/03/26 职场文书
专升本学生毕业自我鉴定
2014/10/04 职场文书
奖学金个人总结
2015/03/04 职场文书
2015年五一劳动节演讲稿
2015/03/18 职场文书