ljfrocky 2015-05-30 19:39:00 25529次浏览 18条评论 36 15 1

在Yii2框架中,如果在表单中使用了验证码,会发现一个奇怪的小问题,就是刷新网页时验证码图片不会跟着刷新。

网上的解决方法

网上的大多数解决方法都是通过修改vendor/yiisoft/yii2/captcha/CaptchaAction.php中的代码来解决,以下两种方法可以任选其一:

1.修改getVerifyCode()方法的参数默认值
修改参数默认值
将参数$regenerate的默认值由false改为true,这样在不传参数的情况下,程序每次获取验证码时都会重新生成。

2.修改run()方法
传递参数
在红色箭头指向的地方中,添加一个参数true,同样可以解决问题。

带来的问题

使用上面两种方法确实都可以解决验证码不刷新的问题,但这样会带来一个新的问题,就是在开启表单客户端验证(enableClientValidation)的情况下,即使用户输入了正确的验证码,网页仍然会提示“验证码错误”:
验证码错误

那肿么办呢?在这里我们可以选择关闭表单的客户端验证功能,以此来解决这个问题:
关闭客户端验证
但这种解决方法不是很完美,因为关闭了客户端的验证功能后,表单数据就只能提交到后台后再验证了,这样无疑会增加服务器的压力。

完美解决方法

上面说了那么多,解决方法貌似都不是很完美,其实要完美解决验证码不刷新的问题十分简单,我们不需要修改CaptchaAction.php,只要修改vendor/yiisoft/yii2/captcha/CaptchaValidator.php这个文件就可以了,修改的地方见下图:
完美解决方法
在红色箭头指向的地方,将参数false改为true即可完美解决问题。

总结

归根到底,是因为yii2在渲染Captcha小部件的时候,会先输出js验证代码,然后再渲染验证码图片,也就是说,验证码字符串必须在输出js代码前就要重新生成,而CaptchaAction.php中的run()方法是渲染验证码图片的时候调用的,CaptchaValidator.php中的clientValidateAttribute()是输出js代码的时候调用的,所以接下来的道理,相信大家都已经明白了。

完:)

觉得很赞
  • 评论于 2015-06-19 11:43 举报

    支持一下,虽然现在用的是yii1版本,但相信2版本会成为主流。

    觉得很赞
  • 评论于 2015-06-29 18:54 举报

    mark下~

  • 评论于 2015-07-03 14:31 举报

    已get.

  • 评论于 2015-08-05 11:22 举报

    感谢分享,已赞

  • 评论于 2015-08-05 11:23 举报

    good

  • 评论于 2015-09-09 17:17 举报

    修改源码。这个是大忌吧,有没有外部配置可以达到要求
    怎么用composer管理。

    1 条回复
    评论于 2015-09-15 12:32 回复

    楼主果然厉害。 可以不用改自己写个类重写下里边的方法就ok了

  • 评论于 2015-11-02 16:49 举报

    非常抱歉,我把你这个提议提交给yii2了,不知道他们会不会修改。见这里

    1 条回复
    评论于 2015-12-30 10:09 回复

    在sitecontroller(框架自带的控制器)中写验证码,点击刷新一切都是正常的,但是自己写的控制器就会出问题(不刷新或者点击不刷新).应该是我们写的时候写错什么了(主要还是没清楚框架)

  • 评论于 2015-11-10 16:02 举报

    通过把你的问题解决方案反馈给开发者,他们并没有采纳,原因见https://github.com/yiisoft/yii2/issues/10071#event-458678122

    虽然在一定程度上可以解决,但还是不够完美。

  • 评论于 2015-11-10 16:28 举报

    通过把你的问题解决方案反馈给开发者,他们并没有采纳,原因见https://github.com/yiisoft/yii2/issues/10071#event-458678122

    虽然在一定程度上可以解决,但还是不够完美。

    1 条回复
    评论于 2016-05-05 11:28 回复

    I understood what you're saying. During AJAX calls in the form may happen when you're focusing another input so re-generating captcha code each would've been too weird.

    觉得很赞
  • 评论于 2016-01-27 10:23 举报

    支持大家解决问题

  • 评论于 2016-01-27 10:28 举报

    我也发个吧
    在PHP中

    public function actions()
    	{
    		return array(
    			 'captcha' => array(
    				  'class' => 'yii\captcha\CaptchaAction',
    				  'maxLength' => 5,
    				  'minLength' => 5,
    				  'width'=>120,
    				  'height'=>'27',
    			 ),
    		 );
    	 }
    

    这个大家都知道,在页面中我没用YII的form,而是自己写的表单

    <input type="text" id="codeid" name="checkcode" class="form-control" placeholder="验证码">
                        <div class="input-group-addon" id="logincode">
                        	
                          <img src="/res/images/logincode.gif" id="code_img" alt="点击刷新">
                        </div>
    

    且看JS部分

    <script>
    $(function(){
    	$("#codeid").focus(function(){
    		$.get('<?php echo Yii::$app->urlManager->createUrl('site/captcha');?>?',{refresh:1},function(data){
    			evaldata=eval(data);
    			$("#code_img").attr('src',evaldata.url);	
    		});	
    	});
    	$("#code_img").click(function(){
    		$.get('<?php echo Yii::$app->urlManager->createUrl('site/captcha');?>',{refresh:1},function(data){
    			evaldata=eval(data);
    			$("#code_img").attr('src',evaldata.url);	
    		});
    	});
    })
    </script>
    

    我们通过向/site/captcha?refresh=1发送GET请求,得到的数据如下,

    {"hash1":538,"hash2":538,"url":"/backend/web/site/captcha?v=56a8243edb9a8"}
    

    很清楚的我们得到了一个新的验证码URL,
    这里说下V,V是用PHP的uniqid()生成的一个唯一码
    这个方法不用改YII的任何代码哦

    如果你在model里面进行两次验证码的验证那么你的验证就会通不过哦。

    YII的验证码不论是生成的时候还是验证的时候都是通过了getVerifyCode,验证通过后会重新在生成一次验证码,所以在model里如果你调用了两次验证的话,就通不过哦

    1 条回复
    评论于 2017-03-31 14:53 回复

    這个方法给力,直接在model的rules验证就添加参数验证就可以了,。但是我修改actions方法的captcha的大小就不生效了。

    觉得很赞
  • 评论于 2016-06-28 11:54 举报

    完美解决了我的问题

  • 评论于 2016-07-26 12:50 举报

    字体 无法获取 怎么解决

  • 评论于 2016-07-26 15:03 举报

    完美完美完美

  • 评论于 2016-12-27 16:19 举报

    Thanks

  • 评论于 2017-03-08 14:57 举报

    这种修改源码的方式不可取,不过给我提示去查看原类,发现有
    /**

     * @var integer how many times should the same CAPTCHA be displayed. Defaults to 3.
     * A value less than or equal to 0 means the test is unlimited (available since version 1.1.2).
     */
    public $testLimit = 3;
    

    这个属性控制这个验证码可以被有效使用几次。 只需要指定1就可以了。

    觉得很赞
  • 评论于 2021-02-17 10:14 举报

    微信图片_20210217101349.png

  • 评论于 2024-04-09 12:06 举报

    不改后端,直接在试图页面js模拟点击:
    比如我的验证码字段定义为verifycode,则会生成loginform-verifycode-image的图像框,直接在页面的js中加入:
    $(function (){ $('#loginform-verifycode-image').trigger("click"); });
    实测效果也可以。

您需要登录后才可以评论。登录 | 立即注册