CCaptchaAction,Yii中的验证码工具bug修复方案


前段时间做登陆功能,涉及到了一个验证码的插件。想到Yii框架自带的一个CCaptcha的扩展,轻松许多。

1、先用CActiveForm做了个登陆的表单,

2、然后往里面添加一个CCaptcha的widget

<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>

表单组合出来后的效果图:

登陆表单


看似不错,但是测试后发现验证码怎么输入都提示错误。想不明白,我是完全按照手册API上的步骤做的,不可能会有错误啊。

百度/谷歌无果后,决定仔细看一下这个CCaptcha内部的结构。

既然验证码只是起到一个验证的功能,那就先看看它的验证过程。

找到 CCaptchaAction::validate()这个方法,发现有这么一行代码:


$session[$name] = $session[$name] + 1;
if($session[$name] > $this->testLimit && $this->testLimit > 0)
        $this->getVerifyCode(true);
其中$session[$name]记录了验证码的使用次数。


发现问题了,我设置了testLimit这个参数等于1。而且,登陆表单还打开了ajax验证以及提交前验证功能。

知道问题在哪了吧,testLimit表示这个验证码只能用一次,而表单的Ajax过程中验证了很多次了,导致系统中的验证码早就更换了,而页面中展示的还是第一次生成的验证码图片。

解决这个问题的办法就是让验证码在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;
    }
}

?>

至此,验证码不再‘飘忽不定’。一切都这么美好!!!




你可能感兴趣的:(bug,CCaptchaAction,验证码bug,CCaptchaAction)