【问题标题】:How to refresh captcha image on page refresh/load?如何在页面刷新/加载时刷新验证码图像?
【发布时间】:2011-09-04 08:05:08
【问题描述】:

我想强制我的网站在每次加载时刷新验证码图像,所以我有一个由 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 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() 方法中的授权用户权限授予验证码操作,仅此而已。还有什么可以发的吗?

【问题讨论】:

  • 首先,您需要click(),而不是click - 您需要调用该方法,而不是获取其内容。
  • 是的,当然,你是对的,出于绝望,我尝试了几种替代方法,似乎我在这里粘贴了其中一种。使用 click() 它不起作用.. html 显示:Refrescar imagen 我的表单中有一个按钮,如下所示: 和相关的函数 function CallFunction() { document.getElementById('yw0_button').click();这不起作用。我错过了什么?非常感谢 Piskvor
  • 这很奇怪。每次我刷新页面时,验证码图像都会发生变化。您可以发布相关的 MVC 文件,我们可以尝试看看这里发生了什么。 (如果你喜欢,因为你已经有工作了)
  • 亲爱的 Soph,我认为问题的标题可以重命名为常见的名称,例如“如何使用 YII 框架刷新验证码图像?”。你可以看看我下面的建议。希望你会喜欢。
  • @Ezze 谢谢 Ezze!刚改了名字。

标签: javascript frameworks refresh captcha yii


【解决方案1】:

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

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

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

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

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

然后在我的js文件中:

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

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

    CCaptchaActionrun() 方法被覆盖,并且与原始方法非常相似,除了在设置render_refreshed GET-parameter 并且正在生成新的验证码时执行了一个额外的if-branch飞行和相应的新图像正在被渲染并作为动作的结果返回。

    Captcha 类中引入了公共refresh 变量,默认为false,这意味着小部件的行为类似于CCaptcha 的行为。覆盖renderImage 方法,我们更改了负责准备小部件的输出HTML 代码的代码。更准确地说,这里准备了一个到验证码操作的链接,用作img 标签的src 属性。在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
            )
        );
    }
    

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            【解决方案6】:

            您可以在表单 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,
                ),
              ));
            

            这对我有用。

            我希望它也对你有用

            【讨论】:

              【解决方案7】:

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

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

              在第 154 行

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

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

              【讨论】:

                【解决方案8】:

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

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

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-07-12
                  • 2014-02-14
                  • 2019-06-16
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多