zf2提供了图片验证码Zend\Captcha\Image和符号字符验证码Zend\Captcha\Figlet,图片验证码是网站应用中见得比较多的一种验证码,本文以图片验证码为例。
如果用session来临时保存生成的验证码,就需要先配置session。
session的参数配置:
// /config/autoload/local.php return array( 'session' => array( 'config' => array( 'class' => 'Zend\Session\Config\SessionConfig', 'options' => array( 'name' => 'zf2ttttt', ), ), 'storage' => 'Zend\Session\Storage\SessionArrayStorage', 'validators' => array( 'Zend\Session\Validator\RemoteAddr', 'Zend\Session\Validator\HttpUserAgent', ), ), );
Application启动后调用session_start:
// /module/Application/Module.php namespace Application; use Zend\Mvc\ModuleRouteListener; use Zend\Mvc\MvcEvent; use Zend\Session\SessionManager; use Zend\Session\Container; class Module { public function onBootstrap(MvcEvent $e) { $eventManager = $e->getApplication()->getEventManager(); $moduleRouteListener = new ModuleRouteListener(); $moduleRouteListener->attach($eventManager); //为表单验证对象设置默认的语言翻译器,以便验证码验证不通过时用默认语言提示用户 \Zend\Validator\AbstractValidator::setDefaultTranslator($e->getApplication()->getServiceManager()->get('translator')); //启动session $this->bootstrapSession($e); } public function bootstrapSession($e){ $session = $e->getApplication()->getServiceManager()->get('Zend\Session\SessionManager'); $session->start(); } //SessionManager工厂 public function getServiceConfig() { return array( 'factories' => array( 'Zend\Session\SessionManager' => function ($sm) { $config = $sm->get('config'); if (isset($config['session'])){ $session = $config['session']; $sessionConfig = null; if (isset($session['config'])){ $class = isset($session['config']['class']) ? $session['config']['class'] : 'Zend\Session\Config\SessionConfig'; $options = isset($session['config']['options']) ? $session['config']['options'] : array(); $sessionConfig = new $class; $sessionConfig->setOptions($options); } $sessionStorage = null; if (isset($session['storage'])){ $class = $session['storage']; $sessionStorage = new $class; } $sessionSaveHandler = null; if (isset($session['save_handler'])){ $sessionSaveHandler = $sm->get($session['save_handler']); } $sessionManager = new SessionManager($sessionConfig, $sessionStorage, $sessionSaveHandler); } else { $sessionManager = new SessionManager(); } Container::setDefaultManager($sessionManager); return $sessionManager; }, ), ); } }
表单Form中添加验证码输入:验证码就是一张图片,可以在表单中用一个text让用户输入验证码,text旁显示验证码图片:
// /module/Test/src/Test/Form/TestForm.php namespace Test\Form; ...... use Test\Form\MyImgCaptchaValidator;//自定义的验证码检验类 class TestForm extends Form implements InputFilterProviderInterface{ ...... public function __construct($name = null) { ...... //添加验证码输入框 $this->add(array( 'name' => 'cv', 'type' => 'Text', 'options' => array( 'label' => '请输入检验码:', ), 'attributes' => array( 'size' => 20, 'maxlength' => 4, ), )); ...... } public function getInputFilterSpecification() { ...... //自定义的验证码检验对象 $captchaValidator = new MyImgCaptchaValidator(); ...... return array( ...... 'cv' => array( 'required' => true, 'filters' => array( array('name' => 'StringTrim'), array('name' => 'StringToLower'), ), 'validators' => array( array('name' => 'NotEmpty'), array( 'name' => 'StringLength',//本例将验证码长度限制为4字符 'options' => array( 'encoding' => 'UTF-8', 'min' => 4, 'max' => 4, ), ), $captchaValidator, ), ), ); } }
自定义的验证码验证类:
// /module/Test/src/Test/Form/MyImgCaptchaValidator.php namespace Test\Form; use Zend\Validator\AbstractValidator; use Zend\Session\Storage\SessionArrayStorage; class MyImgCaptchaValidator extends AbstractValidator { const DIFFERENT = 'different'; protected $messageTemplates = array( self::DIFFERENT => "Capthca inputted is different !",//此处为字符串的key,如果语言文件配置了该字符串,并且为validator设置了默认的tranlaotr,validator基类会自动翻译该字符串 ); public function isValid($value) { $this->setValue($value); $isValid = true; $sessionKey_Capthca = 'sesscaptcha'; $sessionStorage = new SessionArrayStorage(); $captchaWord = $sessionStorage->offsetGet($sessionKey_Capthca);//获取session临时保存的验证码 $wd = $captchaWord; if ($wd != $value){//比较输入的验证码和生成的验证码 $this->error(self::DIFFERENT);//输入不正确,则设置错误消息 $isValid = false; } return $isValid; } }
在视图中输出验证码输入框和验证码图片:
// /module/Test/src/view/test/test/testform.phtml echo '<div>'; $captcha = $this->tform->get('cv');//获取验证码输入框表单元素 echo $formLabel->openTag().$captcha->getOption('label'); echo $this->formInput($captcha);//显示验证码输入框 echo '<img src="'.$imgSrc.'"></div>';//显示验证码图片,$imgSrc为控制器传过来 echo $this->formElementErrors($captcha);//显示错误消息 echo $formLabel->closeTag(); echo '</div>';
控制器代码:
// /module/Test/src/Test/Controller/TestController.php namespace Test\Controller; use Zend\Captcha\Image; use Zend\Session\Storage\SessionArrayStorage; class TestController extends AbstractActionController { public function testformAction() { ...... if ($this->getRequest()->isPost()){//用户提交了表单,处理表单数据 $postData = array_merge_recursive( $this->getRequest()->getPost()->toArray(), $this->getRequest()->getFiles()->toArray() ); $form->setData($postData); if ($form->isValid()) {//表单检验成功 ..... } ...... } //session $sessionStorage = new SessionArrayStorage(); //创建验证码 $sessionKey_Capthca = 'sesscaptcha'; $icv = new \Zend\Captcha\Image();//zf2只支持生成*.png格式图片 $icv->setFont('public/fonts/arial.ttf');//指定字体文件,可以从windows系统文件夹"WINDOWS\Fonts"下拷贝一个“arial.ttf”文件到/public/fonts目录下 $icv->setFontSize(14); $icv->setHeight(30); $icv->setWidth(80); $icv->setDotNoiseLevel(20);//添加像素点的干扰,默认值100 $icv->setLineNoiseLevel(2);//添加像素线的干扰,默认值5 $icv->setImgDir('public/captcha/'); //特别需要注意的是,imgDir和imgUrl这2个参数,如果设置不当,很容易出现无法创建图片文件或者无法显示图片文件的问题。 //下面对这2个参数的设置和默认值做了以下整理: //imgDir:默认值是public/images/captcha。 //imgUrl:默认值是/images/capthca。 //可见,默认值是按照网站把/public设置为web根目录来定的。 //setImgDir:如果是以根目录符"/"开头,则认为是绝对路径,例如,setImgDir('/public/captcha/');则图片保存路径为/public/capthca/asdfas.png; // 如果不是以根目录符"/"开头,则以网站根目录为根,设置的值为网站根目录下的子目录,例如,setImgDir('public/captcha/');则图片保存路径为WebRoot/public/capthca/asdfas.png(WebRoot为网站web根目录); //setImgUrl:如果是以根目录符"/"开头,则以网站根目录为根,例如,setImgUrl('/public/captcha/');则图片URL为http://xxxx/public/capthca/asdfas.png; // 如果不是以根目录符"/"开头,则以当前route为为根,例如,假设当前表单URL为http://x/test/testform,那么调用setImgUrl('public/captcha/');则图片URL为http://x/test/public/capthca/asdfas.png; //综上所述,正确的设置这2个参数的方法是,setImgDir的参数“不要”以“/”开头,setImgUrl的参数“要”以“/”开头。 $icv->setImgUrl('/public/captcha/'); $icv->setWordlen(4);//设置字符个数,默认是8个字符 //创建新的验证码的值 $icv->generate(); //验证码图片的URL $imgSrc = $icv->getImgUrl().'/'.$icv->getId().$icv->getSuffix(); //验证码的字符串 $captchaWord = $icv->getWord(); //验证码保存到session $sessionStorage->offsetSet($sessionKey_Capthca, $captchaWord); return array( 'tform' => $form, 'imgSrc' => $imgSrc,//将验证码图片的url传给视图 ); } }
另外,由于自定义验证码验证类使用了一个字符串"Capthca inputted is different !",因此,需要在语言文件中配置一下该字符串的中文信息。
添加语言文件配置:
// /module/Test/config/module.config.php return array( ...... 'translator' => array( 'translation_files' => array( array( 'type' => 'phparray', 'filename' => __DIR__ . '/../language/my_zh_CN.php',//自己创建的语言文件my_zh_CN.php,保存在/module/Test/language/目录下 ), ), ), ...... );
在语言文件中添加字符串:
// /module/Test/language/my_zh_CN.php return array( "Capthca inputted is different !" => "验证码输入不正确!" );
有时候,验证码不看不清楚的时候,可能需要点击刷新。要实现点击刷新的功能,可以对以上代码做一些如下修改。
控制器中生成验证码的部分剪切出来放在一个函数中:
// /module/Test/src/Test/Controller/TestController.php class TestController extends AbstractActionController { public function createCaptcha(){ //创建验证码 $sessionKey_Capthca = 'sesscaptcha'; $icv = new \Zend\Captcha\Image();//zf2只支持生成*.png格式图片 $icv->setFont('public/fonts/arial.ttf');//指定字体文件,可以从windows系统文件夹"WINDOWS\Fonts"下拷贝一个“arial.ttf”文件到/public/fonts目录下 $icv->setFontSize(14); $icv->setHeight(30); $icv->setWidth(80); $icv->setDotNoiseLevel(20);//添加像素点的干扰,默认值100 $icv->setLineNoiseLevel(2);//添加像素线的干扰,默认值5 $icv->setImgDir('public/captcha/'); //特别需要注意的是,imgDir和imgUrl这2个参数,如果设置不当,很容易出现无法创建图片文件或者无法显示图片文件的问题。 //下面对这2个参数的设置和默认值做了以下整理: //imgDir:默认值是public/images/captcha。 //imgUrl:默认值是/images/capthca。 //可见,默认值是按照网站把/public设置为web根目录来定的。 //setImgDir:如果是以根目录符"/"开头,则认为是绝对路径,例如,setImgDir('/public/captcha/');则图片保存路径为/public/capthca/asdfas.png; // 如果不是以根目录符"/"开头,则以网站根目录为根,设置的值为网站根目录下的子目录,例如,setImgDir('public/captcha/');则图片保存路径为WebRoot/public/capthca/asdfas.png(WebRoot为网站web根目录); //setImgUrl:如果是以根目录符"/"开头,则以网站根目录为根,例如,setImgUrl('/public/captcha/');则图片URL为http://xxxx/public/capthca/asdfas.png; // 如果不是以根目录符"/"开头,则以当前route为为根,例如,假设当前表单URL为http://x/test/testform,那么调用setImgUrl('public/captcha/');则图片URL为http://x/test/public/capthca/asdfas.png; //综上所述,正确的设置这2个参数的方法是,setImgDir的参数“不要”以“/”开头,setImgUrl的参数“要”以“/”开头。 $icv->setImgUrl('/public/captcha/'); $icv->setWordlen(4);//设置字符个数,默认是8个字符 //创建新的验证码的值 $icv->generate(); //验证码图片的URL $imgSrc = $icv->getImgUrl().'/'.$icv->getId().$icv->getSuffix(); //验证码的字符串 $captchaWord = $icv->getWord(); $sessionStorage = new SessionArrayStorage(); //验证码保存到session $sessionStorage->offsetSet($sessionKey_Capthca, $captchaWord); return $imgSrc; } }
创建一个刷新验证码图片的控制器Action:
// /module/Test/src/Test/Controller/TestController.php class TestController extends AbstractActionController { public function refreshcaptchaAction() { $imgSrc = $this->createCaptcha(); return new JsonModel(array( 'imgSrc' => $imgSrc )); } }
视图中添加刷新验证码按钮:
// /module/Test/view/test/test/testform.phtml echo '<div>'; $captcha = $this->tform->get('cv'); echo $formLabel->openTag().$captcha->getOption('label'); echo $this->formInput($captcha); echo '<img id=imgcaptcha src="'.$imgSrc.'"></div>'; echo $this->formElementErrors($captcha); echo $formLabel->closeTag(); echo '<input type="button" value="刷新" onclick="javascript:refreshCaptcha();"/>'; echo '</div>';
添加刷新验证码图片的客户端脚本:
// /module/Test/view/test/test/testform.phtml <script> function refreshCaptcha(){ var ul = '/test/refreshcaptcha'; //alert(ul); $.ajax({ type : "GET", url : ul, dataType : "json", success : function(data, textStatus) { $("#imgcaptcha").attr("src",data.imgSrc); }, error : function(r, t, r){ } }); } </script>
时间: 2024-10-11 07:36:46