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

时间:2011-05-29 15:06:11

标签: javascript frameworks refresh captcha yii

我想强制我的网站每次加载时刷新验证码图像,所以我有一个用onload()事件触发的javascript方法。在这里,我有以下几行:

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到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()方法中的授权用户权限授予验证码操作,这就是所有权限。还有其他我可以发布的内容吗?

8 个答案:

答案 0 :(得分:6)

如果有人在开始使用Yii时遇到类似的问题..这就是我解决触发点击的CAPTCHA问题的方法:我有一个事件触发了onload事件,其中包含以下代码:

$( '#yw0_button')点击();

肯定有一个更好的方法,我愿意接受建议!然而,作为临时解决方案,这可以正常工作,每次加载页面时刷新验证码图像。祝你好运!

编辑:我所做的是像我这样处理html页面的onload事件

<body onload="initialize()"> 
.. 
</body> 

然后在我的js文件中:

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

答案 1 :(得分:5)

我希望我能提出一个更好的方法来解决 Soph 提到的问题。我知道这不是与JavaScript相关的解决方案,这个问题是沉迷于但我可以看到这是最正确的方法。

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

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

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

后者是CCaptchaAction,它通过生成验证码和创建图像来完成提供验证码的最重要工作。考虑到Yii被设计为面向对象,我们可以创建一些我们自己的类CaptchaCaptchaActionCCaptchaCCaptchaAction相对扩展,并将它们放在我们的Web应用程序目录的components子目录。

我对这两个类的实现如下。

run()的{​​{1}}方法被覆盖并且与原始方法非常相似,只是在设置CCaptchaAction GET参数时执行了一个额外的if - 分支。即时生成新验证码并且正在渲染相应的新图像并将其作为操作结果返回。

公共render_refreshed变量已在refresh类中引入,默认为Captcha,表示小部件的行为与false类似。覆盖CCaptcha方法我们改变了负责准备小部件输出HTML代码的代码。更具说服力的是,准备用于验证码操作的链接用作renderImage标记的src属性。如果img成员设置为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 )); 模板中修改captcha的小部件调用:

myView

并且不要忘记通过<?php $this->widget("Captcha", array( 'buttonLabel' => "Generate another code", 'showRefreshButton' => false, 'clickableImage' => true, 'refresh' => $refreshCaptcha )); 替换actions类来修改页面控制器的CCaptchaAction方法:

CaptchaAction

我觉得它按预期工作。希望这会对某人有所帮助。

答案 2 :(得分:1)

我想在Ezze的回答中添加一些内容:

要使clientValidation正常工作,您可以使用自定义验证码验证:

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()),                          
    );
}

答案 3 :(得分: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;
});

答案 4 :(得分:1)

您可以在表单beginWedget之前编写脚本。

在每个页面上加载生成新的验证码。

  $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,
    ),
  ));

这对我有用。

我希望它也适合你

答案 5 :(得分:1)

这是另一种(正确?)方式(discussion)

Yii::app()->getController()->createAction('captcha')->getVerifyCode(true);

答案 6 :(得分:1)

我使用过:http://www.yiiframework.com/extension/captcha-extended/

并更改CaptchaExtendedAction.php(路径:extensions / captchaExtended)

第154行

$this->renderImage($this->getVerifyCode());  

$this->renderImage($this->getVerifyCode(true));

答案 7 :(得分:0)

我为你们提供了更好的解决方案:

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

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