2010-03-19 32 views
17

Tôi đã bao gồm Zend_Form_Element_Hash vào biểu mẫu nhiều biểu mẫu. Tôi có jQuery thiết lập để bắn ra một yêu cầu AJAX khi một hộp kiểm được nhấp vào, tôi vượt qua các mã thông báo với yêu cầu AJAX này. Yêu cầu AJAX đầu tiên hoạt động tốt, nhưng các yêu cầu tiếp theo không thành công.Làm thế nào để sử dụng Zend Framework Form Hash (mã thông báo) với AJAX

Tôi nghi ngờ nó có thể là mã thông báo đã được xác thực rồi sau đó bị xóa khỏi phiên (hop = 1).

Kế hoạch tấn công của bạn để đảm bảo một biểu mẫu với Zend Framework Hash sẽ sử dụng AJAX để hoàn thành một số yêu cầu này là gì?

Trả lời

9

Cuối cùng tôi đã từ bỏ sử dụng Zend_Form_Element_Hash và chỉ cần tạo một mã thông báo theo cách thủ công, đăng ký nó bằng Zend_Session và sau đó kiểm tra nó khi gửi.

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"; 
} 

Điều này dường như làm việc và vẫn giữ những điều tương đối lành mạnh và an toàn. Tôi vẫn muốn sử dụng phần tử Hash, nhưng tôi dường như không thể làm cho nó hoạt động với AJAX.

Cảm ơn tất cả.

2

Băm mẫu thật tuyệt vời về nguyên tắc và một chút ác mộng trong thực tế. Tôi nghĩ cách tốt nhất để xử lý việc này là trả lại giá trị băm mới với phản hồi khi bạn thực hiện yêu cầu và cập nhật đánh dấu biểu mẫu hoặc lưu trữ trong bộ nhớ cho javascript của bạn nếu thích hợp.

Băm mới có thể có sẵn từ đối tượng biểu mẫu hoặc bạn có thể đọc nó từ phiên.

+0

Tôi đã nhận được giá trị thẻ mới từ tôi Biểu mẫu lớp và giá trị mã thông báo đã thay đổi sau khi yêu cầu ajax nhưng mã thông báo của tôi vẫn hết hạn tdhong

1

Bạn đã gợi ý câu trả lời đúng trong câu hỏi của mình: tăng số lượng hop.

Có đề cập cụ thể về điều này trong hướng dẫn sử dụng ZF trực tuyến, nhưng họ đã cập nhật sổ tay của họ và bây giờ tôi không thể tìm thấy nó (cười) - nếu không tôi sẽ đăng liên kết cho bạn.

+0

Có thể xác nhận thứ không hoạt động, nhưng tôi không chắc nó ảnh hưởng như thế nào đến hiệu quả của kiểm tra CSRF. Một lưu ý là tôi tự mở rộng phần tử và tạo ra phần tử của riêng mình, ghi đè phương thức 'initCsrfToken()' - không chỉnh sửa trực tiếp các tệp Zend – dKen

4

Có giải pháp:

Tạo, bên cạnh biểu mẫu chứa dữ liệu, biểu mẫu không có phần tử. Từ bộ điều khiển bạn khởi tạo hai biểu mẫu. Cũng trong bộ điều khiển, bạn thêm phần tử băm vào biểu mẫu trống. Cả hai hình thức nên được gửi đến tầm nhìn. Sau đó, trong điều kiện "if ($ request-> isXmlHttpRequest())" trong bộ điều khiển bạn hiển thị biểu mẫu trống. Sau đó, bạn lấy giá trị băm bằng phương thức "getValue()". Giá trị này phải được gửi bởi Ajax và sau đó sử dụng JavaScript để thay thế giá trị băm đã lỗi thời. Tùy chọn để tạo một biểu mẫu trống cho băm là để tránh các vấn đề với các phần tử khác như captcha mà sẽ có id của nó được tạo lại nếu biểu mẫu được hiển thị và cũng cần phải thay thế thông tin mới. Việc xác nhận sẽ được thực hiện riêng biệt bởi vì có hai hình thức riêng biệt. Sau đó bạn có thể sử dụng lại biểu mẫu băm (trống) bất cứ khi nào bạn muốn. Sau đây là các ví dụ về mã.

//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

8

Đó là làm thế nào để xử lý lĩnh vực băm ở dạng 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; 
    } 
} 

Và sau đó trong kịch bản xem bạn ..

<? $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() ?> 

Hy vọng nó không phải là quá muộn: D

+0

Phần quan trọng ở đây là gọi $ hashElement-> initCsrfToken(); trước khi nhận giá trị. –

0

Nếu y ou muốn sử dụng hình thức xác thực sẽ được sử dụng bên ajax mã sau:

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 
     } 
     # ... 
    } 
} 
Các vấn đề liên quan