前段时间作登录功能,涉及到了一个验证码的插件。想到Yii框架自带的一个CCaptcha的扩展,轻松许多。 php
一、先用CActiveForm作了个登录的表单, web
二、而后往里面添加一个CCaptcha的widget ajax
<dl class="intxt yz"> <dt>验证码:</dt> <dd> <?php $this->widget('CCaptcha', array( 'imageOptions' => array('style' => 'cursor:pointer;width:70px;height:30px;display:inline-block;','id' => 'veryCode'), 'clickableImage' => true, 'buttonLabel' => '换一张', )); ?> <?php echo $form->textField($model,'verifyCode'); ?> <span class="msg"><i></i><?php echo $form->error($model, 'verifyCode', array('class'=>'tso'),false,false); ?></span> </dd> </dl>
表单组合出来后的效果图: session
看似不错,可是测试后发现验证码怎么输入都提示错误。想不明白,我是彻底按照手册API上的步骤作的,不可能会有错误啊。 app
百度/谷歌无果后,决定仔细看一下这个CCaptcha内部的结构。 框架
既然验证码只是起到一个验证的功能,那就先看看它的验证过程。 yii
找到 CCaptchaAction::validate()这个方法,发现有这么一行代码: 测试
$session[$name] = $session[$name] + 1; if($session[$name] > $this->testLimit && $this->testLimit > 0) $this->getVerifyCode(true);其中$session[$name]记录了验证码的使用次数。
发现问题了,我设置了testLimit这个参数等于1。并且,登录表单还打开了ajax验证以及提交前验证功能。 this
知道问题在哪了吧,testLimit表示这个验证码只能用一次,而表单的Ajax过程当中验证了不少次了,致使系统中的验证码早就更换了,而页面中展现的仍是第一次生成的验证码图片。 spa
解决这个问题的办法就是让验证码在ajax提交的时候不执行$session[$name] = $session[$name] + 1;这一行。
根本缘由找到后就开始解决这个问题。代码以下:
<?php /** * @author xiaobo * 继承自yii自带的CCaptchaAction * 若是是ajax提交则不记录提交次数 * example code: class SiteController extends QController { public function actions() { return array( // 验证码 'captcha' => array( 'class' => 'webroot.protected.extensions.captcha.glcaptchaAction', ), ); } } */ class glcaptchaAction extends CCaptchaAction { public function validate($input,$caseSensitive) { $code = $this->getVerifyCode(); $valid = $caseSensitive ? ($input === $code) : !strcasecmp($input,$code); $session = Yii::app()->session; $session->open(); $name = $this->getSessionKey() . 'count'; if(!Yii::app()->request->isAjaxRequest){ $session[$name] = $session[$name] + 1; } if($session[$name] > $this->testLimit && $this->testLimit > 0){ $this->getVerifyCode(true); } return $valid; } } ?>
至此,验证码再也不‘飘忽不定’。一切都这么美好!!!