Veri iki kez veritabanına ekleme durdurmak

15 Cevap php

PHP oldukça yeni im i yöntemler / önlemler diğer programcıların bir kullanıcı bir form olarak aynı sayfada yeniler veri MySQL veritabanı içine iki kez girilen durdurmak için kullanabileceğiniz merak ediyorum? Obviouly olur ve ben bu durdurmak için iyi bir yol gerekir.

Teşekkürler, Ben

15 Cevap

Ben web programlama bir altın kural bu çağırır:

Hiç bir POST isteği için vücut ile cevap vermeyin. Her işi, ve sonra bir Konum cevap: başlığı bu tarayıcı GET ile istediğinde bu yüzden güncellenmiş sayfasına yönlendirmek için.

Bu şekilde, ferahlatıcı herhangi bir zarar vermez.

Ayrıca, burada yorumlarda bir tartışma ile ilgili. Yanlışlıkla doubleclicking, diyelim ki, çifte gönderme korumak için, Gönder düğmesini bir metin dosyasına formun bir md5 () depolamak ve depolanan birine yeni formun md5 karşılaştırın. Eşit iseler, bir çift yazı yaşıyoruz.

Formu işlemek, sonra sonuç sayfasına yönlendirme. Sadece sonuç sayfası redisplays sonra yeniden.

Ilya cevabı ben sadece bir yorum uyabilecek biraz daha eklemek istedim, doğrudur:

Resubmission ([size Ilya tavsiyesi almamış] vb geri dönüyor ve tekrar göndererek, sonuç sayfayı yeniden) tehlikeli ise ben formu sadece bir kez geçmesi emin olmak için bir "seferlik" kullanın.

Form sayfasında:

<?php
@session_start(); // make sure there is a session

// store some random string/number
$_SESSION['nonce'] = $nonce = md5('salt'.microtime());
?>
// ... snip ...
<form ... >
<input type="hidden" name="nonce" value="<?php echo $nonce; ?>" />
</form>

Işleme sayfada:

<?php
if (!empty($_POST)) {
@session_start();

// check the nonce
if ($_SESSION['nonce'] != $_POST['nonce']) {
    // some error condition
} else {
    // clear the session nonce
    $_SESSION['nonce'] = null;
}

// continue processing

Form kez teslim edildikten sonra kullanıcı bilinçli bir ikinci kez doldurduğu sürece, o, tekrar teslim edilemez.

Malumu için (ben ... burada henüz görmedim): Her zaman POST, o yenilemek için / yeniden yazılan sayfa çalışırsa kullanıcının en az bir uyarı alır bu şekilde kullanmak, veri göndermek için GET asla kullanmayın (en azından Firefox, ama ben de diğer tarayıcılarda herhalde).

Iki kez aynı veri için göze alamaz eğer arada, aynı zamanda eşsiz bir anahtar ile bir MySQL çözümü de düşünebilirsiniz (alanların bir arada olabilir) ve olmalıdır:

    INSERT INTO ... ON DUPLICATE KEY UPDATE ...

Ben Gönder düğmesine birden fazla tıklamaları önlemek için (css burada size yardımcı olabilir) orada Ilya katılıyorum ve tıklandığında ya da kalıcı bir iletişim kutusu sunmak oldu kez 'Gönder' düğmesini devre dışı bırakmak için javascript bazı istemci kullanması gerektiğini eklemek istiyorum.

Bunu eklemek için denemeden önce Son olarak, size veritabanındaki verileri istemiyorsanız sonra iki kez de veri için veritabanı kontrol. Yinelenen kayıtları izin veriyoruz ama bir tek kaynaktan hızlı tekrar girmeleri istemiyorsanız o zaman, benim teslim kodu bir zamana dayalı 'lokavt' için izin vermek için bir zaman / tarih damgası ve IP adresi alanlarını kullanmak istiyorum yani eğer IP aynıdır ve son gönderme süresi daha sonra yeni kayıt takmayın az 5 dakika önceydi.

Bu size bazı fikirler verir umuyoruz.

Görüyorsunuz http://en.wikipedia.org/wiki/Post/Redirect/Get, en modern web uygulamaları uygulamak POST / yönlendirme / GET desen kontrol etmek isteyebilirsiniz

Zaten uzak gönderme sayfasından kullanıcı alarak bahsetti iyi önerilerine ek olarak öylesine bir yenileme ve geri düğmesi zararsız, veri depolama iyileştirmede başka bir katman UUID sizin tabloda tuşları olarak s ve kullanmak için Uygulamalarınız onları oluşturmasına izin.

Bu da Microsoft dünyasında Guıd'ler olarak bilinen ve PHP PHP'de uniqid () aracılığıyla birini oluşturabilir. Bu altıgen / ikili sütun biçiminde saklamak gerekir, ancak tablo CHAR daha yoğun kullanılan olacak değilse (32) çalışacak 32 karakter onaltılık değerdir.

Eğer gizli bir giriş olarak formunu görüntülemek ve veritabanı sütunu birincil anahtar olarak işaretlenmiş işaretlemek için emin olun bu kimliği oluşturmak. Kullanıcının tüm yolu geri gönderme sayfasına gitmek için yönetmek yoksa yinelenen tuşları olamaz çünkü Şimdi, INSERT başarısız olur.

Kodda UUID oluşturmak, bu ekstra bir bonus bir ekleme yapmak sonra sen zaten bunu bileceksiniz, çünkü oluşturulan anahtarı almak savurgan sorguları kullanmanız gerekir asla, vardır. Eğer diğer tabloları içine çocuk öğeleri INSERT gerektiğinde bu güzel bir şeydir.

İyi bir programlama çalışması 1 şey dayanarak değil, işinize katmanlarını dayanmaktadır. Kodlayıcılar artımlı kimlikleri güvenmek için ne kadar yaygın olmasına rağmen, onlar bir tablo oluşturmak için tembel yollarından biridir.

Eh, her şeyden önce, en aza indirmek için, bunu onlar veri eklemek form yazı yapmak zorunda bunu yapmak gerekir. Bu şekilde, en azından onlar gerçekten yeniden istiyorsanız güzel küçük onay iletişim soran o alacak.

Bundan daha karmaşık almak, her formda bir gizli bir kez kullanımlık anahtar koyabilirsiniz, ve bu anahtarla formu teslim edildikten sonra onlar aynı anahtar ile bir formu göndermek çalıştığınızda, bir hata görüntüler. Bu anahtar oluşturmak için, muhtemelen bir GUID gibi bir şey kullanmak istiyorum.

(Örneğin, md5(uniqid()) tarafından üretilen) rastgele bir dize ile gizli bir alanı ekleyin, bu dizi için veritabanında bir alan yapmak ve EŞSİZ olun.

You can use a token to prevent the page from being processed again! Such a procedure is used in a lot web frameworks !

The pattern you should use is the "Synchronizer Token Pattern"! If you have a serviceoriented application, you can save your status in the Database.

Veri JavaScript aracılığıyla ya da gizli bir form alanı ile göndermek olabilir.

You should also have a look at libaries with out of the box support for things like this! Grails is such one!

See: http://www.grails.org/1.1-Beta3+Release+Notes ...

<g:form useToken="true">

...

withForm {
   // good request
}.invalidToken {
   // bad request
}

..

Benim iki sent:

  • Veri gönderdikten sonra aynı sayfaya yönlendirir ve doğrulamak if(isset($_POST['submit'])

Benzer durumlarda diğer yararlı bilgiler:

  • LOCK TABLES in MySQL bir görünüm verin

  • İlk tıklamadan sonra JavaScript aracılığıyla düğmeleri devre dışı bırakmak

nasıl ne zaman sayfa yenilendiğinde bilgilerin yeniden göndermeyi sayfası önlemek için. Başka bir sayfaya yönlendirme sayfasından alternatif.

Sayfa yenileme yinelenen kayıt ekleme önlemek için en iyi yolu ..

düğmesine tıklama veritabanındaki kayıtları taktıktan sonra sadece

bu satırı eklemek .......

Response.Write ("location.href = 'yourpage.aspx'");

Mutlu kodlama, zevk

POE (Post Once Exactly) özel başlık kullanılarak çift gönderimleri engellemek için müşteri uyarı amaçlı bir HTTP desen ...

GET /posts/new HTTP/1.1
POE: 1
...

... Ama hala şartnamede.

http://www.mnot.net/drafts/draft-nottingham-http-poe-00.txt

Ben yukarıda Nonce iyi bir çözüm olduğunu düşünüyorum. Istemci birden fazla sekmeyi aynı anda gelen mesajları gerçekleştirmek için çalışıyor eğer ayrı bir oturum değişkeni olarak seferlik saklamak bazı hatalar tanıtacak rağmen. Belki daha iyi ...

$_SESSION['nonces'][] = $nonce;

... Ve ...

if (in_array($_POST['nonce'], $_SESSION['nonces'])) {

... Birden Nonce'lar (nonci? Noncei?) Için izin vermek.

Tercihen çapraz site istek sahtecilik karşı koruyan, aynı zamanda, çift gönderilmesini engellemek için formları şey dahil deneyin. Ben benzersiz bir tek adreste tek bir kullanıcıya bağlıyor, bir form gönderme tanımlayan bir tek kullanımlık alan olan, ben bir formkey dediğimiz kullanmanızı öneririz. Kavramı da başka isimler altında gider, ama ben bağlantılı olduğunuz kısa not yeterince iyi açıklıyor.