Formun yeniden gönderilmesini önleme


107

Birinci sayfa bir HTML formu içerir. İkinci sayfa - gönderilen verileri işleyen kod.

Birinci sayfadaki form gönderilir. Tarayıcı ikinci sayfaya yönlendirilir. Sayfa iki gönderilen verileri ele alır.

Bu noktada, ikinci sayfa yenilenirse, "Formun Yeniden Gönderilmesini Onayla" uyarısı açılır.

Bu önlenebilir mi?



3
burada açıklandığı gibi posta yönlendirmesini kullanın - >> en.wikipedia.org/wiki/Post/Redirect/Get
Meer

Yeniden yönlendirme olmasa bile bunu önleyebilirsiniz. Bakın burada
Eugen Konkov

Yanıtlar:


145

İnsanların burada kullandığı 2 yaklaşım var:

Yöntem 1: AJAX + Yeniden Yönlendirmeyi Kullanın

Bu şekilde, kullanıcı hala sayfa1'in görüntülendiğini görürken, JQuery veya Sayfa2'ye benzer bir şey kullanarak formunuzu arka planda gönderirsiniz. Başarılı bir şekilde gönderdikten sonra, tarayıcıyı Sayfa2'ye yönlendirirsiniz.

Yöntem 2: Gönderi + Kendine Yönlendirme

Bu, forumlarda yaygın bir tekniktir. Sayfa1'deki Form, verileri Sayfa2'ye gönderir, Sayfa2 verileri işler ve yapılması gerekeni yapar ve ardından kendi başına bir HTTP yönlendirmesi yapar. Bu şekilde tarayıcının hatırladığı son "eylem", sayfa2'deki basit bir GET'dir, bu nedenle form F5'ten sonra yeniden gönderilmez.


2
Yöntem 2'nin bir varyantı, başka bir sayfaya yönlendirmedir. Örneğin, example.com/save.html adresine POST yaparsınız ve kaydetme işlemi tamamlandıktan sonra example.com/list.html adresine yönlendirirsiniz .
Guillaume

1
Yöntem 1 ile, müşterinin bir şeyler olduğunu bilmesini sağlamak için BlockUI adlı jQuery eklentisini kullanırdım.
Shikiryu

Yöntem 2'yi kullanıyorum, ancak yenilersem yeniden göndermemi istiyor. Buna benzer bir sorunu olan var mı?
keskin

HTTP yeniden yönlendirmesinin düzgün çalıştığından emin misiniz? Ağ denetçisini / firebug / tarayıcınızda giden HTTP isteklerini incelemek için ne varsa açın ve HTTP çağrılarını kontrol edin. İlkini (form verilerini göndererek) POST yöntemi ile görmeli, Konum başlığı kendisine işaret ederek 301 HTTP kodunu döndürmeli ve hemen ardından GET yöntemi ile aynı sayfaya başka bir HTTP sorgusu görmelisiniz.
CodeTwice

@CodeTwice: Benim durumumda, page1, page2'ye gönderiler, page2 verileri işler ve bir sayfa gösterir (şablona aktarılan değerler ile) .. Yönlendirme nerede gerçekleşmeli? .. Sayfada bir GET isteği yok.
user1050619

24

PRG - Post / Redirect / Get kalıbını kullanmanız gerekir ve PRG'nin P'sini uyguladınız. Yönlendirmeniz gerekiyor . (Şimdi hiç yönlendirmeyi günler gerekmez. Bkz bu )

PRG, bazı mükerrer form gönderimlerini önleyen bir web geliştirme tasarım modelidir; bu, Formu Gönder (Talep Sonrası 1) -> Yönlendirme -> Al (İstek 2) anlamına gelir.

Under the hood

Yeniden yönlendirme durum kodu - HTTP 302 ile HTTP 1.0 veya HTTP 303 ile HTTP 1.1

Yönlendirme durum koduna sahip bir HTTP yanıtı, ek olarak konum başlığı alanında bir URL sağlar. Kullanıcı aracısı (örneğin bir web tarayıcısı), konum alanında belirtilen yeni URL'ye ikinci, aksi halde aynı olan ikinci bir talepte bulunmaya bu kodla bir yanıtla davet edilir.

Yeniden yönlendirme durum kodu, bu durumda web kullanıcısının tarayıcısının, ilk HTTP POST isteğinin yeniden gönderilmesine neden olmadan sunucu yanıtını güvenli bir şekilde yenileyebilmesini sağlamak içindir.

Double Submit Problem

Çift Gönderim Sorunu

Post/Redirect/Get Solution

Gönder / Yeniden Yönlendir / Çözüm Al

Kaynak


2
İyi açıklama. Yönlendirme yapıldıktan sonra kullanıcı tarayıcıdaki geri düğmesine tıklarsa ne olacağını merak ediyorum. "Form yeniden gönderimini onayla" açılır penceresi tekrar gösterilecek. Sanırım onay açılır penceresi tekrar gösterilmese bile, 1. sayfada aynı verilere sahip bir gönderi isteği tekrar yapılacak ve kullanıcı bir kez daha 2. sayfaya yönlendirilecek. Bir dizi form, form1, form2, form3 var. "n" formundan sorunsuz bir şekilde "n-1" formuna nasıl geri dönülür. Rastgele soru: PRG tasarım modelini nerede incelediniz
Rpant

@Rpant üzerinde chrome konum üstbilgisini gönderen php dosyası tarayıcı geçmişinde görünmez, bu nedenle geri düğmesi sizi forma geri götürür.
FluorescentGreen5

@Angelin yönlendirdikten sonra verileri nasıl alacak? Örneğin / bazı_url'ye bazı veriler gönderirken ve bir GET isteğinde bulunan / bir_url'ye yönlendirdiğimde. / Some_url genel olduğundan ve / some_url / <id> gibi bir kimliği içermediğinden yanıtın ne olması gerektiğini nasıl bilebilirim?
Amit Tripathi

@AmitTripathi kendiniz yaratmalısınız. Örneğin: POST talebi, müşteri verilerinin girilmesi olabilirken GET, başarıyla eklenen verilerin görüntülenmesi olabilir. Verileri, form verilerinden başka bir şey olmadığı gibi gösterebilecek veya veritabanına başarılı bir şekilde ekledikten sonra aldığınız müşteri kimliğiyle o müşteri için veritabanından getirerek müşteri sayfasının görünümünü yeniden kullanabileceksiniz.
Angelin Nadar

Ancak @Eugen Konkov çözümüne katılıyorum
Angelin Nadar

10

Doğrudan yapamazsınız ve bu iyi bir şey. Tarayıcının uyarısının bir nedeni var. Bu ileti dizisi sorunuzu yanıtlamalıdır:

Geri düğmesinin POST onay uyarısını göstermesini engelle

Önerilen iki temel çözüm, PRG modeli ve bir AJAX gönderimi ve ardından bir komut dosyası yeniden konumlandırmasıydı.

Yönteminiz bir POST gönderme yöntemine değil de GET'e izin veriyorsa, bunun hem sorunu çözeceğini hem de kurallara daha iyi uyacağını unutmayın. Bu çözümler, POST verilerini istediğiniz / vermeniz gerektiği varsayımına göre sağlanır.


8

Aynı formun asla iki kez gönderilmediğinden% 100 emin olmanın tek yolu, çıkardığınız her birine benzersiz bir tanımlayıcı yerleştirmek ve hangilerinin sunucuda gönderildiğini izlemektir. Buradaki tuzak şudur ki, kullanıcı formun bulunduğu sayfayı yedekleyip yeni veriler girerse, aynı form çalışmayacaktır.


6

Cevabın iki bölümü var:

  1. Yinelenen yayınların, sunucu tarafındaki verilerinizle uğraşmadığından emin olun. Bunu yapmak için, postaya benzersiz bir tanımlayıcı yerleştirin, böylece sonraki istekleri sunucu tarafında reddedebilirsiniz. Bu model, mesajlaşma açısından Idempotent Receiver olarak adlandırılır .

  2. Kullanıcının her ikisinin de yinelenen gönderim olasılığından rahatsız olmadığından emin olun

    • POST'tan sonra bir GET'e yönlendirme (POST yönlendirme GET kalıbı)
    • javascript kullanarak düğmeyi devre dışı bırakma

2'nin altında yaptığınız hiçbir şey, mükerrer başvuruları tamamen engellemez. İnsanlar çok hızlı tıklayabilir ve hackerlar yine de gönderi yapabilir. Yinelenenlerin olmadığından kesinlikle emin olmak istiyorsanız her zaman 1'e ihtiyacınız vardır.


2

POST verileri içeren bir sayfayı yenilerseniz, tarayıcı yeniden gönderiminizi onaylayacaktır. GET verilerini kullanırsanız, mesaj görüntülenmeyecektir. Ayrıca ikinci sayfanın gönderimi kaydettikten sonra veri içermeyen üçüncü bir sayfaya yönlendirmesini de sağlayabilirsiniz.


2

Kimsenin bu numaradan bahsetmediğini buldum.

Yeniden yönlendirme olmadan, yenileme sırasında form onayını yine de engelleyebilirsiniz.

Varsayılan olarak, form kodu şu şekildedir:

<form method="post" action="test.php">

şimdi değiştir <form method="post" action="test.php?nonsense=1">

Sihri göreceksin.

Sanırım bunun nedeni, URL'de bir GET yöntemi (sorgu dizesi) alırsa tarayıcılar onay uyarısı açılır penceresini tetiklemeyecek.


2

Bunu jquery kullanarak yapabilirsiniz

<script>
   $(document).ready(function(){
   window.history.replaceState('','',window.location.href)
   });
</script>

Bu, geri gönderme nedeniyle veriyi gönderdikten sonra tekrar önlemenin en zarif yoludur.

Bu yardımcı olur umarım.


0

PRG kalıbı yalnızca sayfanın yenilenmesinden kaynaklanan yeniden gönderimi engelleyebilir. Bu% 100 güvenli bir önlem değildir.

Yeniden gönderimi önlemek için genellikle aşağıdaki önlemleri alacağım:

  1. İstemci Tarafı - Form gönderimini tetikleyecek bir düğmenin çift tıklamalarını önlemek için javascript kullanın. İlk tıklamadan sonra düğmeyi devre dışı bırakabilirsiniz.

  2. Sunucu Tarafı - Gönderilen parametreler üzerinde bir hash hesaplayacağım ve bu hash'i oturum veya veritabanına kaydedeceğim, böylece yinelenen gönderim alındığında kopyayı ve ardından istemciye uygun yanıtı tespit edebiliriz. Ancak, istemci tarafında bir karma oluşturmayı başarabilirsiniz.

Çoğu durumda, bu önlemler yeniden gönderimi önlemeye yardımcı olabilir.


0

@ Angelin'in cevabını çok beğendim. Ancak bunun pratik olmadığı bazı eski kodlarla uğraşıyorsanız, bu teknik sizin için işe yarayabilir.

Dosyanın en üstünde

// Protect against resubmits
if (empty($_POST))  {
   $_POST['last_pos_sub'] = time();
} else {
     if (isset($_POST['last_pos_sub'])){
        if ($_POST['last_pos_sub'] == $_SESSION['curr_pos_sub']) {
           redirect back to the file so POST data is not preserved
        }
        $_SESSION['curr_pos_sub'] = $_POST['last_pos_sub'];
     }
}

Ardından formun sonunda last_pos_subaşağıdaki gibi yapıştırın :

<input type="hidden" name="last_pos_sub" value=<?php echo $_POST['last_pos_sub']; ?>>

0

Tris'i deneyin:

function prevent_multi_submit($excl = "validator") {
    $string = "";
    foreach ($_POST as $key => $val) {
    // this test is to exclude a single variable, f.e. a captcha value
    if ($key != $excl) {
        $string .= $key . $val;
    }
    }
    if (isset($_SESSION['last'])) {
    if ($_SESSION['last'] === md5($string)) {
        return false;
    } else {
        $_SESSION['last'] = md5($string);
        return true;
    }
    } else {
    $_SESSION['last'] = md5($string);
    return true;
    }
}

Nasıl kullanılır / örnek:

if (isset($_POST)) {
    if ($_POST['field'] != "") { // place here the form validation and other controls
    if (prevent_multi_submit()) { // use the function before you call the database or etc
        mysql_query("INSERT INTO table..."); // or send a mail like...
        mail($mailto, $sub, $body); // etc
    } else {
        echo "The form is already processed";
    }
    } else {
    // your error about invalid fields
    }
}

Yazı tipi: https://www.tutdepot.com/prevent-multiple-form-submission/


0

veri eklemeyi önlemek için js kullanın:

if ( window.history.replaceState ) {
    window.history.replaceState( null, null, window.location.href );
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.