2016-09-04 64 views
4

爲了處理表單我使用下面的代碼(僅用於測試):如何防止在Yii2中提交多個表單?

$(document).on("beforeSubmit", "#test-form", function (event, messages) { 
    $(this).find(':submit').attr('disabled', true); 
    console.log('Test new form'); 
    return false; 
}); 

但是,儘管我做一個提交按鈕爲不活動,我們可以在控制檯中看到,這種形式是當我快速點擊按鈕時,至少提交兩次。作爲一個臨時修復,寫了下面的代碼:

$(document).on("beforeValidate", "form", function(event, messages, deferreds) { 
    $(this).find(':submit').attr('disabled', true); 
    console.log('BEFORE VALIDATE TEST'); 
}).on("afterValidate", "form", function(event, messages, errorAttributes) { 
    console.log('AFTER VALIDATE TEST'); 
    if (errorAttributes.length > 0) { 
     $(this).find(':submit').attr('disabled', false); 
    } 
}); 
$(document).on("beforeSubmit", "#test-form", function (event, messages) { 
    console.log('Test new form'); 
    return false; 
}); 

但不知道這是一個好的決定與否。如何解決這個問題?
在此先感謝!

+1

有人提出使用隨機令牌的解決方案:https://github.com/yiisoft/yii2/issues/10498 –

+0

@Kostas Mitsarakis絕對是一個很好的服務器側的判斷。如果我理解正確,JS不能給予100%的預防這個問題的保證,對吧? – jekahm

+0

是的,因爲JavaScript可以被禁用或因爲瀏覽器問題。 –

回答

4

一個解決方案是使用JavaScript禁用按鈕。但是由於瀏覽器問題或用戶可能在他的瀏覽器中禁用了JavaScript,所以這一直效率不高。

一個不同的解決方案是每次在服務器端檢查表單是否使用保存在會話中的令牌提交。

下面的代碼可以在https://github.com/yiisoft/yii2/issues/10498發現:

型號

public function getHiddenFormTokenField() { 
    $token = \Yii::$app->getSecurity()->generateRandomString(); 
    $token = str_replace('+', '.', base64_encode($token)); 

    \Yii::$app->session->set(\Yii::$app->params['form_token_param'], $token);; 
    return Html::hiddenInput(\Yii::$app->params['form_token_param'], $token); 
} 

「當表單提交,在控制器類名爲‘beforeAction’功能比較發送令牌中的會話值。會話在執行完每個動作之後被清除,如果值不同,則拋出異常。「

控制器

public function beforeAction($action) { 
    $formTokenName = \Yii::$app->params['form_token_param']; 

    if ($formTokenValue = \Yii::$app->request->post($formTokenName)) { 
     $sessionTokenValue = \Yii::$app->session->get($formTokenName); 

     if ($formTokenValue != $sessionTokenValue) { 
      throw new \yii\web\HttpException(400, 'The form token could not be verified.'); 
     } 

     \Yii::$app->session->remove($formTokenName); 
    } 

    return parent::beforeAction($action); 
} 
+0

非常感謝您的幫助! – jekahm