如何在页面刷新/加载时刷新验证码图片?

6
我希望每次网站加载时都能刷新验证码图片,所以我使用一个JavaScript方法来触发onload()事件。在这里,我有以下代码行:
document.getElementById('yw0_button').click;

火狐调试工具(Firebug)没有检测到任何错误,为了测试目的,我在显示行后面添加了一个警告框,每次加载页面时都会弹出。但是,图片不会刷新!以下是我认为与视图文件相关的内容:
<?php if(extension_loaded('gd')): ?>
    <div class="row">
        <?php echo $form->labelEx($model,'verifyCode'); ?>
        <div>
            <?php
            $this->widget('CCaptcha',
                          array('showRefreshButton'=>true,
                                'buttonType'=>'button',
                                'buttonOptions'=>
                                                    array('type'=>'image',
                                                          'src'=>"/path/images/refresh-icon.png",
                                                          'width'=>30,
                                                    ),                                                            
                                'buttonLabel'=>'Refrescar imagen'),
                          false); 
            ?>
            <br>
            <?php echo $form->textField($model,'verifyCode'); ?>
        </div>
    <div class="hint">
        Porfavor ingrese las letras como las ve en la imagen superior.
        <br/>No hay distincion entre minúsculas y mayúsculas.</div>
    </div>
<?php endif; ?>

有什么想法吗?


@k to the z 刚刚看到这个!如果您能帮我找到更合适的解决方案,那就太好了!以下是我认为与视图文件相关的内容:

<?php if(extension_loaded('gd')): ?>
        <div class="row">
            <?php echo $form->labelEx($model,'verifyCode'); ?>
            <div>
                <?php
                $this->widget('CCaptcha',
                              array('showRefreshButton'=>true,
                                    'buttonType'=>'button',
                                    'buttonOptions'=>
                                                        array('type'=>'image',
                                                              'src'=>"/path/images/refresh-icon.png",
                                                              'width'=>30,
                                                        ),                                                            
                                    'buttonLabel'=>'Refrescar imagen'),
                              false); 
                ?>
                <br>
                <?php echo $form->textField($model,'verifyCode'); ?>
            </div>
        <div class="hint">
            Porfavor ingrese las letras como las ve en la imagen superior.
            <br/>No hay distincion entre minúsculas y mayúsculas.</div>
        </div>
    <?php endif; ?>

在控制器中,我在accessRules()方法中授予经授权的用户访问captcha操作的权限,这就是全部。还有其他我可以发布的内容吗?


首先,你需要使用 click() 而不是 click - 你需要调用该方法,而不是获取其内容。 - Piskvor left the building
是的,当然,你说得对。在绝望中,我尝试了几种替代方法,似乎我把其中一个粘贴到这里了。使用click()不起作用... html显示如下:<a href=".../captcha?refresh=1" id="yw0_button">刷新图像</a>我的表单中有一个按钮,如下所示: <input type="button" name="btn" value="10" onclick="CallFunction()"> 和相关的函数 function CallFunction() { document.getElementById('yw0_button').click(); }这不起作用。我错过了什么吗?非常感谢Piskvor。 - Soph
有点奇怪。每次我刷新页面验证码图片都会改变。你可以发布相关的MVC文件,我们可以尝试看看这里发生了什么。(如果您愿意,因为您已经有一个解决方法) - k to the z
1
亲爱的Soph,我认为问题的标题可以改成一些常见的东西,比如“如何使用YII框架刷新验证码图像?”你可以看看我的建议。希望你会喜欢它。 - ezze
@Ezze 谢谢Ezze!刚刚改了名字。 - Soph
8个回答

7
如果有人在使用Yii时遇到类似的问题...我是如何解决CAPTCHA触发点击事件的问题的: 我有一个被onload事件触发的事件,其中包含以下代码: $('#yw0_button').click();
肯定有更好的方法,欢迎提供建议!然而,作为临时解决方案,这个方法完全有效,每次加载页面时都会刷新验证码图片。祝好运!
编辑:我所做的是处理我的HTML页面的onload事件,就像这样
<body onload="initialize()"> 
.. 
</body> 

然后在我的js文件中:

function initialize() 
{ 
     $('#yw0_button').click(); 
} 

5
我希望我能提出一个更好的方法来解决由 Soph提到的问题。我知道这与JavaScript无关,但我认为这是最正确的方法。

我面临着同样的要求-在页面刷新时刷新标题,但在其他字段输入无效时保留该标题,因为在每次验证失败时重复新的验证码很烦人。所以这个任务看起来就像不在POST请求上刷新标题,在其他情况下刷新它(GET请求)。苏菲(Soph)自己提出的解决方案无法实现这一点-因为人们可以知道,POST请求被发送到服务器,客户端JavaScript无法分析其数据。

因此,我决定查看Yii的验证码实现。它由位于system.web.widgets.captcha包中的两个类组成。前者是从CWidget扩展的CCaptcha,我们在视图中使用它以通过以下方式向Web表单添加验证码:

<?php 
    $this->widget("CCaptcha", array(
    'buttonLabel' => "Generate another code",
    'showRefreshButton' => false,
    'clickableImage' => true
));
?>

后者是CCaptchaAction,它通过生成验证码和创建图像来提供验证码的最重要工作。考虑到Yii设计为面向对象,我们可以从CCaptchaCCaptchaAction派生出自己的类CaptchaCaptchaAction,并将它们放置在Web应用程序目录下的components子目录中。
以下是我实现的这两个类: CCaptchaActionrun()方法被覆盖,与原始方法相似,只是当设置了render_refreshed GET参数时,会执行一个额外的if分支,在此处动态生成新的验证码并创建相应的新图像,并将其作为操作结果返回。
Captcha类中引入了一个公共的refresh变量,默认值为false,表示小部件的行为类似于CCaptcha。通过覆盖renderImage方法,我们修改了负责准备小部件输出HTML代码的代码。更准确地说,这是准备用作标记的属性的链接的位置。如果将refresh成员设置为true,则会在此链接后附加一个额外的render_refreshed参数。
以下是CaptchaAction.php
<?php

Yii::import("system.web.widgets.captcha.CCaptchaAction");

class CaptchaAction extends CCaptchaAction
{
    const RENDER_REFRESHED_GET_VAR = "render_refreshed";

    public function run()
    {
        if (isset($_GET[self::REFRESH_GET_VAR]))  // AJAX request for regenerating code
        {
            $code = $this->getVerifyCode(true);
            echo CJSON::encode(array(
                'hash1' => $this->generateValidationHash($code),
                'hash2' => $this->generateValidationHash(strtolower($code)),
                // we add a random 'v' parameter so that FireFox can refresh the image
                // when src attribute of image tag is changed
                'url'=> $this->getController()->createUrl($this->getId(), array(
                    'v' => uniqid()
                )),
            ));
        }
        else if (isset($_GET[self::RENDER_REFRESHED_GET_VAR]))
        {
            $this->renderImage($this->getVerifyCode(true));
        }
        else
            $this->renderImage($this->getVerifyCode());
        Yii::app()->end();
    }
}

以下是 Captcha.php 代码:

<?php

Yii::import("web.system.widgets.CCaptcha");

class Captcha extends CCaptcha
{
    public $refresh = false;

    protected function renderImage()
    {
        if (!isset($this->imageOptions['id']))
            $this->imageOptions['id'] = $this->getId();

        if ($this->refresh)
        {
            $url = $this->getController()->createUrl($this->captchaAction, array(
                'v' => uniqid(),
                CaptchaAction::RENDER_REFRESHED_GET_VAR => 1
            ));
        }
        else
        {
            $url = $this->getController()->createUrl($this->captchaAction, array(
                'v' => uniqid()
            ));
        }
        $alt = isset($this->imageOptions['alt']) ? $this->imageOptions['alt'] : '';
        echo CHtml::image($url, $alt, $this->imageOptions);
    }
}

因此,使用方法非常简单。在为网站页面准备模型数据时,请执行以下操作:
...

// Creating order model's instance
$model = new MyModel();
$refreshCaptcha = true;

if (isset($_POST['MyModel']))
{
    $refreshCaptcha = false;
    ...
}

...

$this->render("myView", array(
    'model' => $model,
    'refreshCaptcha' => $refreshCaptcha
));

然后在此页面操作中的myView模板中修改验证码小部件的调用:

<?php 
    $this->widget("Captcha", array(
    'buttonLabel' => "Generate another code",
    'showRefreshButton' => false,
    'clickableImage' => true,
    'refresh' => $refreshCaptcha
));

不要忘记修改页面控制器的actions方法,将CCaptchaAction类替换为CaptchaAction

public function actions()
{
    return array(
        'captcha'=>array(
            'class'=>'CaptchaAction',
            'backColor'=>0xFFFFFF
        )
    );
}

在我看来,它的工作效果符合预期。希望这能帮助到某些人。


2
这里有另一种(正确?)的做法(讨论)
Yii::app()->getController()->createAction('captcha')->getVerifyCode(true);

1
我想在Ezze的回答中添加一些内容:
为了使客户端验证起作用,您可以使用自定义验证码验证:
class CaptchaValidatorRefresh extends CCaptchaValidator
{
    public function clientValidateAttribute($object,$attribute)
{
    $js="";

    if(!$this->allowEmpty)
    {
        $message=$this->message!==null ? $this->message : Yii::t('yii','The verification code is incorrect.');

        $js="
            if($.trim(value)=='') {
                messages.push(".CJSON::encode($message).");
            }
        ";
    }       
    return $js;
    }
}

然后

public function rules()
{
    return array(
        array('verifyCode', 'CaptchaValidatorRefresh', 'on'=>'request', 'allowEmpty'=>!CCaptcha::checkRequirements()),                          
    );
}

1

1

我有一个更好的解决方案:

public function beforeAction($action)
{
    if($action->id == 'captcha'){
        $action->getVerifyCode(true);
    }
    return parent::beforeAction($action); 
}

把这些代码放入你包含验证码操作的控制器中!

1
请添加以下 JavaScript 代码:
jQuery(document).ready(function() {
    jQuery.ajax({
        'success':function(html){jQuery("#yw0").attr("src",html)},
        'url':'/checkout/finish/captcha?refresh=1',
        'cache':false
    });
    return false;
});

1
你可以在表单开始之前编写脚本。
每次页面加载时生成新的验证码代码。
  $script=' $(document).ready(function() {

            document.getElementById("yw0_button").click();
    });';
  Yii::app()->clientScript->registerScript('yw0_button', $script);

  $form=$this->beginWidget('CActiveForm', array(
    'id'=>'test-form',
    'action'=>Yii::app()->createUrl('controllerName/actionName'),
    'enableClientValidation'=>true, 
    'clientOptions'=>array(
        'validateOnSubmit'=>true,
    ),
  ));

对我来说它有效。

希望这也对你有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接