ป้องกันการส่งแบบฟอร์มต่าง ๆ (ฝั่งเซิร์ฟเวอร์)


9

ฉันพบปัญหาที่ผู้ใช้สามารถส่งฟอร์มใด ๆ ที่สร้างขึ้นโดย Form API หลายครั้ง (การคลิกที่รวดเร็วทำให้เกิดคำขอหลายรายการ)

ฉันได้ใส่โซลูชันพื้นฐานด้านไคลเอนต์ (javascript) ของการปิดใช้งานปุ่ม แต่ฉันอยากรู้ว่าวิธีที่ดีที่สุดในการป้องกันสถานการณ์นี้อยู่ที่ฝั่งเซิร์ฟเวอร์

มีวิธีแนะนำให้ใช้ระบบโทเค็นแบบฟอร์มของ Drupal เพื่อจัดการสิ่งนี้หรือไม่? โดยเฉพาะอย่างยิ่งโซลูชันแบบโกลบอล (เช่นการเพิ่มตัวตรวจสอบความถูกต้องที่กำหนดเองให้กับทุกรูปแบบโดยใช้ hook_form_alter ())

วิธีการของฉันจนเป็นเช่นนี้:

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  $form['#validate'][] = 'mymodule_form_validate';
}

function mymodule_form_validate(&$form, &$form_state){
  //initialize form array
  if (!isset($_SESSION['submitted_forms'])){
    $_SESSION['submitted_forms'] = array();
  }

  $form_token = $form_state['values']['form_token'];
  if ( isset($_SESSION['submitted_forms'][$form_token]) && $_SESSION['submitted_forms'][$form_token] = TRUE ){
    form_set_error('name]', 'This form has already been submitted');
  }
  else{
    $_SESSION['submitted_forms'][$form_token] = TRUE;
  }
}

ฉันพบปัญหาเมื่อ form_token ไม่ซ้ำกับแบบฟอร์ม - ดูเหมือนว่าจะยังคงเหมือนเดิมไม่ว่าจะเกิดอะไรขึ้น ฉันอาจเข้าใจผิดว่าโทเค็นนั้นอยู่ในรูปแบบที่ยิ่งใหญ่ของแบบฟอร์ม API

ความเข้าใจใด ๆ ที่ชื่นชม!


จากการติดตามฉันเริ่มใช้ $ form_state ['form_build_id'] แทนโทเค็น ถ้าฉันส่ง id บิลด์ฟอร์มเดียวกันสองครั้งที่ไหนสักแห่งระหว่างที่ฟอร์มถูกสร้างใหม่และประมวลผลต่อไป
PrairieHippo

คำตอบ:


8

ฉันมีปัญหาเดียวกันและจัดการแก้ไขโดยใช้กลไกการล็อคจาก Drupal

ในฟังก์ชั่นการตรวจสอบฉันใช้:

function mymodule_custom_form_validate($form, &$form_state){
  if (lock_acquire('your_custom_lock_name')) {
    // long operations here
  } else {
    form_set_error("", t("You submitted this form already."));
  }
}

และในฟังก์ชั่นส่งฉันปล่อยล็อค:

function mymodule_custom_form_submit($form, &$form_state){
  // submit code
  lock_release('your_custom_lock_name');
}

1

ที่นี่คุณควรพิจารณาน้ำหนักโมดูล:

  1. หนึ่งโมดูล (ให้ first_module) ซึ่งควรมีโมดูลบน้ำหนักสูงสุด maximum_value (อาจเป็น -2000) ที่นี่ก็ควรใช้ hook_form_alter () ด้วยรหัสต่อไปนี้ตอนนี้คุณควรตรวจสอบว่าฟอร์มของคุณถูกส่งไปแล้วหรือไม่
   function first_module_form_alter(&$form, &$form_state, $form_id)
    {
      $form['#validate'][] = 'mymodule_form_validate';
    }
function mymodule_form_validate(&$form, &$form_state){
  //a($form_state);
  //initialize form array
  if (!isset($_SESSION['submitted_forms'])){
    $_SESSION['submitted_forms'] = array();
  }

  $form_token = $form_state['values']['form_id'];
  if ( isset($_SESSION['submitted_forms'][$form_token]) && $_SESSION['submitted_forms'][$form_token] = TRUE ){
    form_set_error('name]', 'This form has already been submitted');
  }
  else{
    $_SESSION['submitted_forms'][$form_token] = TRUE;
  }
}
  1. second_module ที่มีค่าน้ำหนักสูงกว่าคุณควรยกเลิกการตั้งค่าเซสชันโดยเพิ่มการส่งโทรกลับไปยังโมดูล

function second_module_form_alter (& $ ฟอร์ม, & $ form_state, $ form_id) {$ form ['# submit'] [] = 'mymodule_form_submit'; }

function mymodule_form_submit(&$form, &$form_state){

  $form_token = $form_state['values']['form_id'];
  unset($_SESSION['submitted_forms'][$form_token]);

}

1

หากคุณต้องการฟังก์ชั่นนี้ในทุกรูปแบบและควบคุมได้มากขึ้นโดยไม่ต้องเข้ารหัสดูที่ซ่อนปุ่มส่งโมดูล

คุณสมบัติ:

  1. ซ่อนหรือปิดใช้งานปุ่มส่งหลังจากคลิกแล้ว
  2. แสดงข้อความและ / หรือภาพในขณะที่รอ

5
โมดูลปุ่มซ่อน Submt ไม่ใช่โซลูชันฝั่งเซิร์ฟเวอร์ จากคำอธิบายของโมดูล: "สำหรับเบราว์เซอร์ที่ปิดการใช้งาน Javascript โมดูลนี้จะไม่มีผลกระทบเลย" drupal.org/project/hide_submit
Blake Frederick

0
$form['submit'] = array(
  '#type' => 'submit',
  '#value' => t('Save'),
  '#attributes' => array(
    'onclick' => 'javascript:var s=this;setTimeout(function(){s.value="Saving...";s.disabled=true;},1);',
  ),
);

หวังว่าสิ่งนี้จะช่วย ..

หรือคุณสามารถอ้างอิงการป้องกันการคลิกหลายครั้งของปุ่มส่ง & drupal มีหนึ่งโมดูลซ่อนปุ่มส่ง

ผู้ใช้บางคนคลิกปุ่มส่งมากกว่าหนึ่งครั้งโดยไม่ตั้งใจขณะที่รอการโพสต์ของพวกเขา ในบางกรณีสิ่งนี้อาจส่งผลให้เกิดการโพสต์ซ้ำหรือคำสั่งซื้ออีคอมเมิร์ซที่ซ้ำกัน


-1

นี่คือปัญหาของฉันก่อนหน้านี้ วิธีแก้ปัญหาของฉันคือปิดใช้งานปุ่มผ่าน JS

.โมดูล:

/**
 * Implementation of hook_init().
 */
function myModule_init(){
if (arg(0) == 'node' && (arg(2) == 'edit' || arg(1) == 'add')) {
    //hide btn when clicked on article nodes
    drupal_add_js(drupal_get_path('module', myModule') . '/js/disable-submit.js');
}

JS:

Drupal.behaviors.module_disable_submit = function (context) {

/* 
 * Disable keypress on form fields.
 * Prevent browser to reload when pressing enter in input fields 
 */


$('.buttons input:submit').click(function() {
  $('.buttons input:submit').hide();
  $('#node-form .buttons').prepend('<input type="submit" style="margin:1px 0; box-shadow:0 1px 1px #DDDDDD; border-radius:3px 3px 3px 3px; background:url(/sites/all/themes/rubik/images/bleeds.png) repeat-x scroll 0 -41px #F4F4F4; border-color:#DDDDDD #DDDDDD #CCCCCC; border-style:solid; border-width:1px; color:#B8A98F; cursor:default; font-weight:normal; padding:2px 10px; text-align:center;" value="Saving..." name="op" onclick="return false;" />');
  if ('.buttons input:submit') {
    $('.buttons input:submit').keypress(function() {
      $('.buttons input:submit').parents("form").submit();
      $('.buttons input:submit').hide();
    });
  }
});
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.