基于Zend的Captcha机制的应用


Posted in PHP onMay 02, 2013

如何生成验证码图片?使用php的GD? ok,right。其实Zend的Captcha模块已经封装好了。这篇文章就说一下如何使用Zend的Captcha模块。

环境安装
首先Zend的Captcha需要安装GD。查看有没有安装GD需要去phpinfo()中看是否有GD模块。(注意,有可能出现php -m里面的模块有gd但phpInfo()里面的模块没有gd,这个问题是说明你的PHP和Apache没有安装对。具体请去google之)

(如果在安装gd的过程中提示Missing Dependency: libt1.so.5模块错误,请看这篇文章:http://www.siutung.org/post/730/)

生成验证码图片
使用Zend_Captcha_Image类

$captcha = new Zend_Captcha_Image(); 
$captcha->setWordLen('4') 
    ->setHeight('60') 
    ->setFont(NCHANNEL_FONT_DIR . '/arial.ttf') 
    ->setImgDir(NCHANNEL_CAPTCHA_DIR) 
    ->setDotNoiseLevel('5') 
    ->setLineNoiseLevel('5'); $id = $captcha->generate(); 
$code = $captcha->getWord();

1 这里有两个变量需要说一下,$id 和 $code。

图片文件名就是$id . ".png"; 这个id是一个随机数。

$code是这个图片中的文字,就是验证码的答案

2 setWordLen 等设置的接口是Zend_Captcha_Image暴露给外面的对验证码图片的设置。其实看函数名也能知道是做什么的了。具体请参考Zend的Api手册。

3 font字体文件必须在服务器上有,ImgDir设置的是图片生成路径
 

验证验证码图片
好了,生成了验证码图片,现在要验证验证码了。

验证步骤就需要用到Zend_Session_Namespace这个session存储模块。

首先,生成验证码的时候有id和code两个变量应该存下来。
好吧,回到上一步,将代码进行下修改

$captcha = new Zend_Captcha_Image(); 
$captcha->setWordLen('4') 
    ->setHeight('60') 
    ->setFont(NCHANNEL_FONT_DIR . '/arial.ttf') 
    ->setImgDir(NCHANNEL_CAPTCHA_DIR) 
    ->setDotNoiseLevel('5') 
    ->setLineNoiseLevel('5'); $id = $captcha->generate(); 
$codeSession = new Zend_Session_Namespace('captcha_code_' . $id); 
$codeSession->code = $captcha->getWord();

这里看到,我们使用$captcha_code_$id将code存储下来。目的是等到验证步骤的时候使用。

第二步
给页面传递表单的时候把$id和验证码图片传递过去。

让用户填写验证码。

第三步,验证。
验证这步需要用户提供两个参数: $id 和验证码答案$code

$codeSession = new Zend_Session_Namespace('captcha_code_' . $this->_params['id']); 
if ($codeSession == null || strtolower($codeSession->code) != strtolower($this->_params['code'])) { 
    $this->Output(ERROR); }

这段代码读起来很顺口吧:如果captcha_code_$id中有保存code,并且code和用户填写的code一致,那么就验证成功。

这样,验证码验证过程就结束了。

深入考虑
好了,其实验证码没有这么简单。下面有几个问题值得考虑

验证码图片是不会自动删除的,所以生成的验证码图片所在文件夹体积会不断增加。怎么办?
Image类中是提供了方法的$captcha->setGcFreq(5) 。

具体使用方法看API吧

我希望自己设置$id,怎么办?
答案是在Zend_Captche_Image上再封装一层,然后重写generate()方法

比如我重写了一个类:

class Test_Captcha_Image extends Zend_Captcha_Image 
{ 
    protected $_fid = "";     public function generate() 
    { 
        $word = $this->_generateWord(); 
        $this->_setWord($word); 
        if ($this->_fid) { 
            $id = $this->_fid; 
        } 
        $this->_generateImage($id, $this->getWord()); 
        if (mt_rand(1, $this->getGcFreq()) == 1) { 
            $this->_gc(); 
        } 
        return $id; 
    } 
    public function setId($id) { 
        $this->_fid = $id; 
        return $this; 
    } 
}

我希望我每个用户只有一个验证码,这个验证码的图片名称就是userid.png
 

那么使用这个类的代码是这样的

$captcha = new Test_Captcha_Image(); 
$captcha->setWordLen('4') 
    ->setHeight('60') 
    ->setFont(NCHANNEL_FONT_DIR . '/arial.ttf') 
    ->setImgDir(NCHANNEL_CAPTCHA_DIR) 
    ->setDotNoiseLevel('5') 
    ->setLineNoiseLevel('5') 
    ->setId($user_id); $id = $captcha->generate(); 
$codeSession = new Zend_Session_Namespace('captcha_code_' . $user_id); 
$codeSession->code = $captcha->getWord(); 
--------------   
// 验证session 
$codeSession = new Zend_Session_Namespace('captcha_code_' . $this->_params['user_id']); 
if ($codeSession == null || strtolower($codeSession->code) != strtolower($this->_params['code'])) { 
    $this->Output(ERROR); 
}

附言
Zend的Captcha是封装了基本的验证码动作。生成简单的验证码基本是完全不需要看内部的代码的了,但如果你需要对验证码进行更高级的操作,比如修改验证码的显示文字等,最好就需要将Captcha的源码看一下了。
PHP 相关文章推荐
PHP在字符断点处截断文字的实现代码
Apr 21 PHP
PHP与Java进行通信的实现方法
Oct 21 PHP
php另类上传图片的方法(PHP用Socket上传图片)
Oct 30 PHP
php调整gif动画图片尺寸示例代码分享
Dec 05 PHP
PHP面向对象程序设计之类常量用法实例
Aug 20 PHP
PHP使用Pthread实现的多线程操作实例
Nov 14 PHP
PHP序列化/对象注入漏洞分析
Apr 18 PHP
PHP之图片上传类实例代码(加了缩略图)
Jun 30 PHP
关于PHP中字符串与多进制转换函数的实例代码
Nov 03 PHP
Laravel Intervention/image图片处理扩展包的安装、使用与可能遇到的坑详解
Nov 14 PHP
yii2多图上传组件的使用教程
May 10 PHP
PHP策略模式写法
Apr 01 PHP
PHP静态调用非静态方法的应用分析
May 02 #PHP
Mysql中分页查询的两个解决方法比较
May 02 #PHP
记录mysql性能查询过程的使用方法
May 02 #PHP
基于MySQL分区性能的详细介绍
May 02 #PHP
php中使用$_REQUEST需要注意的一个问题
May 02 #PHP
PHP执行批量mysql语句的解决方法
May 02 #PHP
PHP闭包(Closure)使用详解
May 02 #PHP
You might like
PHP系统流量分析的程序
2006/10/09 PHP
基于jQuery的可用于选项卡及幻灯的切换插件
2011/03/28 Javascript
jQuery EasyUI API 中文文档 - MenuButton菜单按钮使用介绍
2011/10/06 Javascript
JQuery入门—JQuery程序的代码风格详细介绍
2013/01/03 Javascript
在jquery中combobox多选的不兼容问题总结
2013/12/24 Javascript
jquery 删除字符串最后一个字符的方法解析
2014/02/11 Javascript
JavaScript中的对象的extensible属性介绍
2014/12/30 Javascript
jQuery实现鼠标滚轮动态改变样式或效果
2015/01/05 Javascript
javascript实现仿IE顶部的可关闭警告条
2015/05/05 Javascript
JS模拟实现Select效果代码
2015/09/24 Javascript
JS实现浏览器状态栏文字闪烁效果的方法
2015/10/27 Javascript
微信小程序 使用picker封装省市区三级联动实例代码
2016/10/28 Javascript
JavaScript使用ZeroClipboard操作剪切板
2017/05/10 Javascript
第一次记录Bootstrap table学习笔记(1)
2017/05/18 Javascript
浅谈AngularJS中使用$resource(已更新)
2017/09/14 Javascript
vue history 模式打包部署在域名的二级目录的配置指南
2019/07/02 Javascript
微信小程序实现可长按移动控件
2020/11/01 Javascript
python中的对象拷贝示例 python引用传递
2014/01/23 Python
Python字符串逐字符或逐词反转方法
2015/05/21 Python
Python中字符串的常见操作技巧总结
2016/07/28 Python
python matplotlib绘图,修改坐标轴刻度为文字的实例
2018/05/25 Python
Python分割指定页数的pdf文件方法
2018/10/26 Python
Python之lambda匿名函数及map和filter的用法
2019/03/05 Python
节日快乐! Python画一棵圣诞树送给你
2019/12/24 Python
python语言中有算法吗
2020/06/16 Python
写演讲稿所需要注意的4个条件
2014/01/09 职场文书
档案检查欢迎词
2014/01/13 职场文书
模范家庭事迹材料
2014/02/10 职场文书
技能比武方案
2014/05/21 职场文书
班主任寄语2015
2015/02/26 职场文书
2015年员工工作总结范文
2015/04/08 职场文书
2016党员干部政治学习心得体会
2016/01/23 职场文书
经典哲理警句:志不真则心不热,心不热则功不贤
2019/11/14 职场文书
详解MySQL的Seconds_Behind_Master
2021/05/18 MySQL
Sleuth+logback 设置traceid 及自定义信息方式
2021/07/26 Java/Android
MySQL分区表实现按月份归类
2021/11/01 MySQL