1

以下のコードを追加すると、キャプチャのリロードが正常に機能します

ZEND FORM の場合:

 $this->setName("login");
    $this->setMethod('post');

    $this->addElement('text', 'username', array(
    'filters'    => array('StringTrim', 'StringToLower'),
    'validators' => array(
        array('StringLength', false, array(0, 50)),
    ),
    'required'   => true,
    'label'      => 'Username:',
    ));

    $this->addElement('password', 'password', array(
    'filters'    => array('StringTrim'),
    'validators' => array(
        array('StringLength', false, array(0, 50)),
    ),
    'required'   => true,
    'label'      => 'Password:',
     ));


// Add a captcha
$this->addElement('captcha', 'captcha', array(
'label'      => 'Please enter the 5 letters displayed below:',
'required'   => true,
'captcha'    => array(
    'captcha' => 'Figlet',
    'wordLen' => 5,
    'timeout' => 300
)
 ));



  $captcha = $this->createElement('captcha', 'captcha', array(
    'required' => true,
    'captcha' => array(
        'captcha' => 'Image',
        'font' => APPLICATION_PATH . '/../public/fonts/arial.ttf',
        'fontSize' => '24',
        'wordLen' => 5,
        'height' => '50',
        'width' => '150',
        'imgDir' => APPLICATION_PATH.'/../public/captcha',
        'imgUrl' => Zend_Controller_Front::getInstance()->getBaseUrl().'/captcha',
        'dotNoiseLevel' => 50,
        'lineNoiseLevel' => 5,
    ),
    'description' => 'Refresh Captcha Image'

  ));

  $captcha->setLabel('Please type the words shown:');
  $captcha->removeDecorator("htmlTag")->removeDecorator('label');
  $captcha->addDecorator('Errors', array('class' => 'err-username', 'style' => 'display:none'));
  $captcha->addDecorator('Description', array('id' => 'refreshcaptcha'));

    $this->addElement($captcha);
 $this->getElement('captcha')->removeDecorator("htmlTag")->removeDecorator('label');

// And finally add some CSRF protection
  /*$this->addElement('hash', 'csrf', array(
'ignore' => true,
 ));*/

 $this->addElement('submit', 'login', array(
'required' => false,
'ignore'   => true,
'label'    => 'Login',
 ));

phtml で:

    <script type="text/javascript">
    $(document).ready(function() {
        $('#refreshcaptcha').click(function() { 
            $.ajax({ 
                url: "<?php echo $this->url(array('controller' => 'auth', 'action' => 'refresh'), 'default', false) ?>", 
                dataType:'json', 
                success: function(data) { 
                    $('#contactForm img').attr('src', data.src); 
                    $('#captcha-id').attr('value', data.id); 
                }
            }); 
        }); 
    });
    </script>

    <?php
        //Default
        //$this->form->setAction($this->url());
        //echo $this->form;
    ?>

    <?php 
    $errorsMessages = $this->form->getMessages();
    //http://www.websitefactors.co.uk/zend-framework/2011/06/error-class-on-form-field-errors-using-zend-form/
    ?>
    <?php 
    foreach($this->form->getMessages() as $elemName=>$messages) {
        foreach($messages as $message) {
            $label = $this->form->getElement($elemName)->getLabel();
            echo $this->escape($label.' '.$message)."<br>" ;
        }
    }
    ?>
    <div id="contactForm">
    <form method="<?php echo $this->form->getMethod(); ?>" action="<?php echo $this->form->getAction(); ?>">
    <?php echo $this->form->username->renderViewHelper(); ?>
    <?php echo $this->form->password->renderViewHelper(); ?>
    <?php echo $this->form->captcha; ?>
    <?php //echo $this->form->csrf->renderViewHelper(); ?>
    <?php echo $this->formSubmit('submit', 'Sign in',array('class'=>'button')); ?>
    </form>
    </div>

「キャプチャ画像の更新」をクリックすると、ページを更新せずにキャプチャ画像が置き換えられ、正常に動作しますが、以下のCSRF(クロスサイトリクエストフォージェリ)コードを追加してキャプチャコードをリロードしてから送信すると、ログインできません成功。エラーが表示されます:「値が必要で、空にすることはできません」または「表示されている単語を入力してください: キャプチャ値が間違っています

  $this->addElement('hash', 'csrf', array(
        'ignore' => true,
    ));
4

1 に答える 1

0

Zend_Form_Element_Hash はリクエストごとに生成されます。そのため、「Captcha Image の更新」をクリックすると、新しい要求が生成されます。次に、フォームを送信すると、リクエストを使い果たしているため、トークンが同期されていないため、csrf チェックが失敗します。

これを修正するには、間違ったことをして、ホップ数をいくらか大きくするだけです。ただし、これは、求めているセキュリティを無効にするのに役立ちます。これを正しく修正する 1 つの方法は、refresh() アクションで認証コントローラーのトークンを再初期化することです。次に、この新しいトークンを含む json_encoded 応答を送り返すことができます。

....
$form->captcha->initCsrfToken(); //recreate token and send it back
$responseArray['hash'] =  $form->captcha->getValue();
echo Zend_Json::encode($responseArray);

ajax 呼び出しを行った後、トークンを refresh() アクションから返されたものに置き換えることができます。例:

var newHash = jQuery.parseJSON(data).hash;
$('#yourcsrfelement').val(newHash);
于 2013-03-22T01:05:58.840 に答える