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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6168451/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 19:44:25  来源:igfitidea点击:

How to refresh captcha image on page refresh/load?

javascriptframeworksrefreshcaptchayii

提问by Soph

I want to force my site to refresh the captcha image everytime it loads, so I have a javascript method triggered with the onload() event. Here I have the following line:

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

document.getElementById('yw0_button').click;

Firebug doesn't detect any errors, and for testing purposes I have added an alert right after the displayed line, and the alert pops up each time the page is loaded. However, the image doesn't refresh!

Firebug 没有检测到任何错误,出于测试目的,我在显示的行之后添加了一个警报,并且每次加载页面时都会弹出警报。但是,图像不会刷新!

This is what I believe is relevant about the view file:

这是我认为与视图文件相关的内容:

<?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; ?>

Any ideas?

有任何想法吗?



@k to the zjust saw this! Yes sure, if you could help me find a more proper solution it would be awesome! This is what i believe is relevant about the view file:

@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; ?>

In the controller I grant authorized users permission in the accessRules() method to the captcha action, and thats about all. Is there something else I could post?

在控制器中,我将 accessRules() 方法中的授权用户权限授予验证码操作,仅此而已。还有什么我可以发布的吗?

回答by Soph

In case anyone goes through a similar problem whilst getting started with Yii.. This is how I resolved the CAPTCHA issue triggering a click: I have an event triggered the the onload event, which has the following code:

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

$('#yw0_button').click();

$('#yw0_button').click();

There surely must be a better way, im open to suggestions! However as a temporary solution this works just fine, refreshing the captcha image each time the page is loaded. Good luck!

肯定有更好的方法,我愿意接受建议!但是,作为临时解决方案,这很好用,每次加载页面时刷新验证码图像。祝你好运!

EDIT:What I did was handle the onload event for my html page like this

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

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

Then in my js file:

然后在我的 js 文件中:

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

回答by ezze

I hope I can propose a better way to solve the problem mentioned by Soph. I know this is not JavaScript-related solution this question is addicted to but as I can see this one is the most right way to go.

我希望我能提出一个更好的方法来解决Soph提到的问题。我知道这不是与 JavaScript 相关的解决方案,这个问题让人上瘾,但正如我所见,这是最正确的方法。

I faced the same requirement - to refresh the caption on page refresh but preserve this one when user's input is invalid on other fields because repeating a new verification code on each validation's fail is annoying. So this task looks like to not refresh the caption on POSTrequest and refresh it otherwise (GETrequest). A solution proposed by Sophby himself can't achieve this - as one could know POSTrequests are sent to server and their data cannot be analyzed by client-side JavaScript.

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

Therefore I decided to look at Yii's captcha implementation. It consists of two classes located in system.web.widgets.captchapackage. The former is CCaptchaextended from CWidgetand that we use in our view to add a captcha to web form in the manner like this:

因此我决定看看 Yii 的验证码实现。它由位于system.web.widgets.captcha包中的两个类组成。前者是CCaptchaCWidget我们的观点中扩展而来的,我们使用它以如下方式向 Web 表单添加验证码:

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

The latter is CCaptchaActionthat does the most significant work to provide a captcha by generating a verification code and creating an image. Taking into account that Yii is designed to be object-oriented we can create a couple of our own classes Captchaand CaptchaActionextended from CCaptchaand CCaptchaActionrelatively and place them in componentssubdirectory of our web application's directory.

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

My implementation of both these classes is below.

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

run()method of CCaptchaActionis overriden and is quite similar to original one excepting that there is one additional if-branch executing when render_refreshedGET-parameter is set and where new verification code is being generated on the fly and corresponding new image is being rendered and returned as action's result.

run()的方法CCaptchaAction被覆盖并且与原始方法非常相似,除了ifrender_refreshed设置 GET 参数时执行一个额外的分支,并且正在动态生成新的验证码,并且正在呈现相应的新图像并将其作为操作的结果返回。

A public refreshvariable has been introduced in Captchaclass and defaults to falsemeaning widget's behavior is similar to CCaptcha's one. Overriding renderImagemethod we alter a code responsible for preparing widget's output HTML code. To be more precisive it's where a link to captcha action is prepared used as srcattribute of an imgtag. In the case of refreshmember is set to truean additional render_refreshedparameter is appended to this link.

类中refresh引入了一个公共变量Captcha,默认为false意味着小部件的行为类似于 的行为CCaptcha。覆盖renderImage方法我们更改负责准备小部件输出 HTML 代码的代码。更准确地说,它准备了一个到验证码操作的链接,用作标签的src属性img。在refresh成员设置为true附加render_refreshed参数的情况下附加到此链接。

Here is CaptchaAction.php:

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

And this is Captcha.php:

这是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);
    }
}

So the usage is quite simple. In action preparing model's data for site's page do the following:

所以用法很简单。在为站点页面准备模型数据时,请执行以下操作:

...

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

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

...

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

After that modify captcha's widget call in myViewtemplate of this page's action:

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

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

and don't forget to modify actionsmethod of page's controller by replacing CCaptchaActionclass by CaptchaAction:

并且不要忘记actions通过将CCaptchaAction类替换为以下内容来修改页面控制器的方法CaptchaAction

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

Seems to me that it works as expected. Hope this will help somebody.

在我看来,它按预期工作。希望这会帮助某人。

回答by Bulki S Maslom

I'd like to add something to the Ezze's answer:

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

To make clientValidation working, you can use custom captcha validation:

要使 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;
    }
}

and then

接着

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

回答by Nanhe Kumar

Add this javascript:

添加这个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;
});

回答by Kailas

You can write the script before form beginWedget.

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

on every page load generate the new captcha code.

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

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

it's work for me.

这对我有用。

I hope it's also work for you

我希望它也适合你

回答by Ben

Here's another (correct?) way to do it (discussion):

这是另一种(正确的?)方法(讨论)

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

回答by saeedeh

I have used : http://www.yiiframework.com/extension/captcha-extended/

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

and change CaptchaExtendedAction.php (path: extensions/captchaExtended)

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

in line 154

在第 154 行

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

to

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

回答by ThinkAlone

I have a better solution for you guys:

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

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

Put these codes into the controller which you include captcha action!

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