为什么Yii2验证码无法通过验证在客户端?

时间:2014-11-14 05:01:09

标签: ajax yii2 captcha

我正在使用Yii2 admin 模块,验证码图像显示在表单上。输入验证码后,提示始终在客户端显示错误消息,但我确定输入正确。然后我查看源代码,我发现我没有正确设置属性captchaAction\yii\captcha\CaptchaValidator), captchaAction 的默认值为{ {1}},但我的控制器是site/captcha,我认为captchaAction的值应该是app\modules\admin\controllers\PublicController,但是如何设置呢?

以下是我的浏览页面代码:

admin/public/captcha

这是我的控制器:

<?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [
    'template' => '<div class="row"><div class="col-lg-4">{image}</div> &nbsp;<div class="col-lg-7">{input}</div></div>',
    'captchaAction' => 'public/captcha',
 ]); ?>

5 个答案:

答案 0 :(得分:3)

小心使用由AJAX验证的表单。如果您通过Ajax验证,将重新加载Yii的Captcha。所以在这种情况下,我们可以用两个选项来解决:

  1. 禁用ajaxValidation,启用clientValidation。如:注册表格
  2. $form = ActiveForm::begin([
        'id'                     => 'registration-form',
        'enableAjaxValidation'   => true,
        'enableClientValidation' => false
    ]);
    
    1. 覆盖CaptchaAction的功能验证,通过AJAX不要getVerifyCode
    2. if(\Yii::$app->request->isAjax == false) {
          $this->getVerifyCode(true);
      }
      

答案 1 :(得分:2)

在SiteController外部使用验证码时,您应该在3个文件中进行更改:

  1. 在模型路径方法中定义captchaAction,您自己定义了验证码验证:

    function rules()
    {
        return [
            ...
            ["verificationCode", "captcha", 'captchaAction' => 'your-controller/captcha']
        ];
    }
    
  2. 在控制器中定义验证码操作:

    public function actions()
    {
        return [
            'error' => [
                'class' => 'yii\web\ErrorAction',
            ],
            'captcha' => [
                'class' => 'yii\captcha\CaptchaAction',
                'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
            ],
        ];
    }
    
  3. 在视图文件中更改图像渲染操作:

    <?= $form->field($model,
        "verificationCode")->widget( Captcha::className(), [
            'captchaAction' => 'your-controller/captcha'
        ]); ?>
    

答案 2 :(得分:1)

问题和更好的解决方案。

基本上,问题通常是在为整个活动表单设置enableAjaxValidation时引起的,代码如下所示。

<?php $form = ActiveForm::begin([
    'id' => 'some-id',
    'enableAjaxValidation' => true,
    'enableClientValidation' => false,
]); ?>

默认是使用客户端幻灯片验证,但有时事情只能在服务器端验证,因此这个功能可以很好。除了全局选项之外,每个输入都可以指定是否使用enableAjaxValidation。但是出于某种原因,Captcha小部件没有明确地将其设置为false

在大多数情况下,某些输入需要进行AJAX验证,最好将其保留为默认值,并为所需的控件启用它。例如,如果我们有一个用户注册表单,我们有一个AJAX验证器来检查重复的用户名,我们可以只为那一个输入启用它。

<?= $form->field($model, 'username', ['enableAjaxValidation' => true]) ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= $form->field($model, 'verifyCode')->widget(Captcha::className()) ?>

这样做也为我们带来了一些其他好处,例如通过验证客户端可以减少AJAX请求,并在可能的情况下提供更快的响应时间。

上面不是那么好的选择:

以下是基于@AnHuy's answer的旧备用解决方案。

在具有captcha操作的控制器中(SiteController,如果使用Yii2启动项目),请找到actions部分。

    public function actions() {
        return [
            // ...
            'captcha' => [
                'class' => 'yii\captcha\CaptchaAction',
                'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
            ],
            // ...
        ];
    }

yii\captcha\CaptchaAction替换为您自己的类路径,该路径将继承Yii操作,在这种情况下,我将使用app\models\captcha\CaptchaAction

    public function actions() {
        return [
            // ...
            'captcha' => [
                'class' => 'app\models\captcha\CaptchaAction',
                'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
            ],
            // ...
        ];
    }

现在创建动作子类,在本例中为models/captcha/CaptchaAction.php

<?php

namespace app\models\captcha;

use Yii;
use yii\captcha\CaptchaAction as CaptchaActionBase;

class CaptchaAction extends CaptchaActionBase {
    public function validate($input, $caseSensitive) {
        // Skip validation on AJAX requests, as it expires the captcha.
        if (Yii::$app->request->isAjax) {
            return true;
        }
        return parent::validate($input, $caseSensitive);
    }
}

基本上它会检查它是否是AJAX验证检查,并在这种情况下返回true,跳过过期的验证检查。如果没有,它会正常运行验证。

答案 3 :(得分:0)

更改模型表单规则

   ['verifyCode', 'captcha','captchaAction'=>'public/captcha' ],

答案 4 :(得分:0)

确保您拥有&#39;验证码&#39;在您的角色的访问规则

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'actions' => ['captcha', (whatever ...)],
                    'allow' => true,
                ],

...