如何将 Zend Framework 表单哈希(令牌)与 AJAX 结合使用

发布于 2024-08-26 03:41:17 字数 234 浏览 7 评论 0原文

我已将 Zend_Form_Element_Hash 包含到表单 multiplecheckbox 表单中。我将 jQuery 设置为在单击复选框时触发 AJAX 请求,我通过此 AJAX 请求传递令牌。第一个 AJAX 请求运行良好,但后续请求失败。

我怀疑一旦令牌被验证,它就会从会话中删除(hop = 1)。

使用 Zend Framework Hash 保护表单并使用 AJAX 完成其中一些请求的攻击计划是什么?

I have included Zend_Form_Element_Hash into a form multiplecheckbox form. I have jQuery set to fire off an AJAX request when a checkbox is clicked, I pass the token with this AJAX request. The first AJAX request works great, but the subsequent ones fail.

I suspect it may be once the token has been validated it is then removed from the session (hop = 1).

What would be your plan of attack for securing a form with Zend Framework Hash yet using AJAX to complete some of these requests?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

紫轩蝶泪 2024-09-02 03:41:17

我最终放弃使用 Zend_Form_Element_Hash 并只是手动创建一个令牌,用 Zend_Session 注册它,然后在提交时检查它。

form.php

$myNamespace = new Zend_Session_Namespace('authtoken');
$myNamespace->setExpirationSeconds(900);
$myNamespace->authtoken = $hash = md5(uniqid(rand(),1));
$auth = new Zend_Form_Element_Hidden('authtoken');
$auth->setValue($hash)
     ->setRequired('true')
     ->removeDecorator('HtmlTag')
     ->removeDecorator('Label');    

controller.php

$mysession = new Zend_Session_Namespace('authtoken');
$hash = $mysession->authtoken;
if($hash == $data['authtoken']){
    print "success";
} else {
    print "you fail";
}

这似乎有效并且仍然保持相对理智和安全。我仍然宁愿使用 Hash 元素,但我似乎无法使其与 AJAX 一起使用。

谢谢大家。

I finally abandoned using Zend_Form_Element_Hash and just created a token manually, registered it with Zend_Session and then checked it upon submission.

form.php

$myNamespace = new Zend_Session_Namespace('authtoken');
$myNamespace->setExpirationSeconds(900);
$myNamespace->authtoken = $hash = md5(uniqid(rand(),1));
$auth = new Zend_Form_Element_Hidden('authtoken');
$auth->setValue($hash)
     ->setRequired('true')
     ->removeDecorator('HtmlTag')
     ->removeDecorator('Label');    

controller.php

$mysession = new Zend_Session_Namespace('authtoken');
$hash = $mysession->authtoken;
if($hash == $data['authtoken']){
    print "success";
} else {
    print "you fail";
}

This seems to work and still keeps things relatively sane and secure. I'd still rather use the Hash element, but I can't seem to make it work with AJAX.

Thanks all.

扛起拖把扫天下 2024-09-02 03:41:17

这就是如何以 ajax 形式处理哈希字段:

class AuthController extends Zend_Controller_Action
{
    public function init()
    {
        $contextSwitch = $this->_helper->getHelper('contextSwitch');
        $contextSwitch->addActionContext('index', 'json')
                      ->initContext();
    }

    public function loginAction()
    {
        $form = new Application_Form_Login();
        $request = $this->getRequest();

        if ($request->isPost()) {
            if ($form->isValid($request->getPost())) {
                // some code ..
            } else {
                // some code ..

                // Regenerate the hash and assign to the view
                $reservationForm->hash->initCsrfToken();
                $this->view->hash = $reservationForm->hash->getValue();
            }
        }
        $this->view->form = $form;
    }
}

然后在您的视图脚本中..

<? $this->dojo()->enable()
                ->requireModule('dojox.json.query')
                ->onLoadCaptureStart() ?>
function() {
    var form = dojo.byId("login_form")
    dojo.connect(form, "onsubmit", function(event) {
        dojo.stopEvent(event);

        var xhrArgs = {
            form: this,
            handleAs: "json",
            load: function(data) {
                // assign the new hash to the field
                dojo.byId("hash").value = dojox.json.query("$.hash", data);

                // some code ..
            },
            error: function(error) {
                // some code ..
            }
        }
        var deferred = dojo.xhrPost(xhrArgs);
    });
}
<? $this->dojo()->onLoadCaptureEnd() ?>

希望还不算太晚:D

That's how to handled hash field in ajax form :

class AuthController extends Zend_Controller_Action
{
    public function init()
    {
        $contextSwitch = $this->_helper->getHelper('contextSwitch');
        $contextSwitch->addActionContext('index', 'json')
                      ->initContext();
    }

    public function loginAction()
    {
        $form = new Application_Form_Login();
        $request = $this->getRequest();

        if ($request->isPost()) {
            if ($form->isValid($request->getPost())) {
                // some code ..
            } else {
                // some code ..

                // Regenerate the hash and assign to the view
                $reservationForm->hash->initCsrfToken();
                $this->view->hash = $reservationForm->hash->getValue();
            }
        }
        $this->view->form = $form;
    }
}

And then in your view script ..

<? $this->dojo()->enable()
                ->requireModule('dojox.json.query')
                ->onLoadCaptureStart() ?>
function() {
    var form = dojo.byId("login_form")
    dojo.connect(form, "onsubmit", function(event) {
        dojo.stopEvent(event);

        var xhrArgs = {
            form: this,
            handleAs: "json",
            load: function(data) {
                // assign the new hash to the field
                dojo.byId("hash").value = dojox.json.query("$.hash", data);

                // some code ..
            },
            error: function(error) {
                // some code ..
            }
        }
        var deferred = dojo.xhrPost(xhrArgs);
    });
}
<? $this->dojo()->onLoadCaptureEnd() ?>

Hope it's not too late :D

漫雪独思 2024-09-02 03:41:17

有一个解决方案:

除了包含数据的表单之外,创建一个不包含元素的表单。您可以从控制器实例化这两种形式。同样在控制器中,您将元素哈希添加到空表单中。两种形式都应发送至愿景。然后,在控制器中的条件“if ($request->isXmlHttpRequest())”中,您呈现空表单。然后,使用“getValue()”方法获取哈希值。该值必须通过 Ajax 作为响应发送,然后使用 JavaScript 替换已经过时的哈希值。为哈希创建空表单的选项是为了避免其他元素(例如验证码)出现问题,如果呈现表单,验证码将再次生成其 id,并且还需要替换新信息。由于有两种不同的形式,验证将单独进行。稍后您可以随时重复使用哈希(空)形式。以下是代码示例。

//In the controller, after instantiating the empty form you add the Hash element to it:
$hash = new Zend_Form_Element_Hash('no_csrf_foo');
$hash_form->addElement('hash', 'no_csrf_foo', array('salt' => 'unique'));

 //...

//Also in the controller, within the condition "if ($request->isXmlHttpRequest())" you render the form (this will renew the session for the next attempt to send the form) and get the new id value:
$hash_form->render($this->view);
$hash_value['hash'] = $hash_form->getElement('no_csrf_foo')->getValue();//The value must be added to the ajax response in JSON, for example. One can use the methods Zend_Json::decode($response) and Zend_Json::encode($array) for conversions between PHP array and JSON.

//---------------------------------------

//In JavaScript, the Ajax response function:
document.getElementById("no_csrf_foo").value = data.hash;//Retrieves the hash value from the Json response and set it to the hash input.

狮子座

There is a solution:

Create, besides the form that will contain the data, a form without elements. From the controller you instantiate the two forms. Also in the controller, you add the element hash to the empty form. Both forms should be sent to the vision. Then, in the condition "if ($ request-> isXmlHttpRequest ())" in the controller you render the empty form. Then, you take the hash value with the method "getValue ()". This value must be sent in response by Ajax and then use JavaScript to replace the hash value that is already obsolete. The option to create an empty form for the hash is to avoid problems with other elements such as captcha that would have its id generated again if the form were rendered, and would also need to have the new information replaced. The validation will be done separately because there are two distinct forms. Later you can reuse the hash (empty) form whenever you want. The following are examples of the code.

//In the controller, after instantiating the empty form you add the Hash element to it:
$hash = new Zend_Form_Element_Hash('no_csrf_foo');
$hash_form->addElement('hash', 'no_csrf_foo', array('salt' => 'unique'));

 //...

//Also in the controller, within the condition "if ($request->isXmlHttpRequest())" you render the form (this will renew the session for the next attempt to send the form) and get the new id value:
$hash_form->render($this->view);
$hash_value['hash'] = $hash_form->getElement('no_csrf_foo')->getValue();//The value must be added to the ajax response in JSON, for example. One can use the methods Zend_Json::decode($response) and Zend_Json::encode($array) for conversions between PHP array and JSON.

//---------------------------------------

//In JavaScript, the Ajax response function:
document.getElementById("no_csrf_foo").value = data.hash;//Retrieves the hash value from the Json response and set it to the hash input.

Leo

金兰素衣 2024-09-02 03:41:17

表单哈希原则上很好,但在实践中却有点噩梦。我认为处理此问题的最佳方法是在发出请求时返回带有响应的新哈希,并根据需要更新表单标记或存储在内存中的 JavaScript。

新的哈希值可以从表单对象中获得,或者您可以从会话中读取它。

Form hashes are great in principle and a bit of a nightmare in practice. I think the best way to handle this is to return the new hash with the response when you make a request, and update the form markup or store in memory for your javascript as appropriate.

The new hash may be available from the form object, or you can read it from the session.

老娘不死你永远是小三 2024-09-02 03:41:17

您在问题中暗示了正确的答案:增加跳数。

ZF 在线手册中具体提到了这一点,但他们更新了手册,现在我找不到它(笑) - 否则我会为您发布链接。

You hinted at the right answer in your question: increase the hop count.

There was specific mention of this in the ZF manual online, but they updated their manuals and now i can't find it (grin)- otherwise i would have posted the link for you.

り繁华旳梦境 2024-09-02 03:41:17

如果您想在ajax端使用表单验证器,请使用以下代码:

Myform.php

class Application_Form_Myform extends Zend_Form
{ 
    # init function & ... 
    public function generateform($nohash = false)
    { 
        # Some elements
        if(!$nohash)
        {
           $temp_csrf = new Zend_Session_Namespace('temp_csrf'); 
           $my_hash = new Zend_Form_Element_Hash ( 'my_hash' );
           $this->addElement ( $my_hash , 'my_hash');  
           $temp_csrf->hash = $my_hash->getHash();
        }
        # Some other elements
    }
}

AjaxController.php

class AjaxController extends Zend_Controller_Action
{ 
    // init ... 
    public function validateAction()
    { 
         # ... 
         $temp_csrf = new Zend_Session_Namespace('temp_csrf');
         if($temp_csrf->hash == $params['received_hash_from_client'])
         {
             $Myform     = new Application_Form_Myform(); 
             $Myform->generateform(true);
             if($AF_Bill->isValid($params))
             {
                 # Form data is valid
             }else{
                 # Form invalid
             }
         }else{
             # Received hash from client is not valid
         }
         # ... 
    }
}

If you want to use form validator in ajax side use following code :

Myform.php

class Application_Form_Myform extends Zend_Form
{ 
    # init function & ... 
    public function generateform($nohash = false)
    { 
        # Some elements
        if(!$nohash)
        {
           $temp_csrf = new Zend_Session_Namespace('temp_csrf'); 
           $my_hash = new Zend_Form_Element_Hash ( 'my_hash' );
           $this->addElement ( $my_hash , 'my_hash');  
           $temp_csrf->hash = $my_hash->getHash();
        }
        # Some other elements
    }
}

AjaxController.php

class AjaxController extends Zend_Controller_Action
{ 
    // init ... 
    public function validateAction()
    { 
         # ... 
         $temp_csrf = new Zend_Session_Namespace('temp_csrf');
         if($temp_csrf->hash == $params['received_hash_from_client'])
         {
             $Myform     = new Application_Form_Myform(); 
             $Myform->generateform(true);
             if($AF_Bill->isValid($params))
             {
                 # Form data is valid
             }else{
                 # Form invalid
             }
         }else{
             # Received hash from client is not valid
         }
         # ... 
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文