解决Yii2中刷新网页时验证码不刷新的问题 [ 2.0 版本 ]
在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代码的时候调用的,所以接下来的道理,相信大家都已经明白了。
完:)
ljfrocky
最后登录:2015-07-07
在线时长:3小时39分
- 粉丝9
- 金钱120
- 威望20
- 积分350
共 18 条评论
支持一下,虽然现在用的是yii1版本,但相信2版本会成为主流。
mark下~
已get.
感谢分享,已赞
good
修改源码。这个是大忌吧,有没有外部配置可以达到要求
怎么用composer管理。
楼主果然厉害。 可以不用改自己写个类重写下里边的方法就ok了
非常抱歉,我把你这个提议提交给yii2了,不知道他们会不会修改。见这里
在sitecontroller(框架自带的控制器)中写验证码,点击刷新一切都是正常的,但是自己写的控制器就会出问题(不刷新或者点击不刷新).应该是我们写的时候写错什么了(主要还是没清楚框架)
通过把你的问题解决方案反馈给开发者,他们并没有采纳,原因见https://github.com/yiisoft/yii2/issues/10071#event-458678122
虽然在一定程度上可以解决,但还是不够完美。
通过把你的问题解决方案反馈给开发者,他们并没有采纳,原因见https://github.com/yiisoft/yii2/issues/10071#event-458678122
虽然在一定程度上可以解决,但还是不够完美。
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.
支持大家解决问题
我也发个吧
在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里如果你调用了两次验证的话,就通不过哦
這个方法给力,直接在model的rules验证就添加参数验证就可以了,。但是我修改actions方法的captcha的大小就不生效了。
完美解决了我的问题
字体 无法获取 怎么解决
完美完美完美
Thanks
这种修改源码的方式不可取,不过给我提示去查看原类,发现有
/**
* @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就可以了。
不改后端,直接在试图页面js模拟点击:
比如我的验证码字段定义为verifycode,则会生成loginform-verifycode-image的图像框,直接在页面的js中加入:
$(function (){ $('#loginform-verifycode-image').trigger("click"); });
实测效果也可以。