Bir GET isteği neden sunucudaki verileri değiştirmemeli?


109

İnternet üzerinden aşağıdaki önerileri görüyorum:

Bir GET hiçbir zaman sunucudaki verileri değiştirmemelidir; bunun için bir POST isteği kullanın.

Bu fikrin temeli nedir?

Veritabanına veri ekleyen bir php servisi yaparsam ve onu GET sorgu dizgisine geçirirsem, neden bu yanlış? (SQL Injection ile ilgilenmek için hazırlanmış ifadeleri kullanıyorum). POST isteği bir şekilde daha güvenli midir?

Yoksa bunun tarihi bir nedeni var mı? Eğer öyleyse, bu tavsiye bugün ne kadar geçerli?




Bu soruyu sorduğun için teşekkür ederim, ve iyi ifade edilmiş cevap için teşekkür ederim. Bu soruyu sormak isteyenleri göndermek için her zaman bir referansa ihtiyacım vardı :)
Benjamin Gruenbaum


2
@JoachimSauer GET, tarayıcıdan onları kurtarmış olsa da, kök problem kimlik doğrulama eksikliğidir. Herhangi bir senaryo çocuğu onları unutulmaya da kaçırabilirdi.
KodlarInChaos

Yanıtlar:


185

Bu tavsiye değil.

HTTP protokolündeGET bu şekilde A tanımlanır . Düzensiz ve güvenli olması gerekiyordu .

Neden olarak - a GETönbelleğe alınabilir ve bir tarayıcıda yenilenebilir. Tekrar ve tekrar.

Bu, GETtekrar aynısını yaparsanız tekrar veritabanınıza ekleyeceğiniz anlamına gelir .

GETBir bağlantı haline gelirse ve bir arama motoru tarafından taranırsa bunun ne anlama gelebileceğini düşünün . Veritabanınızı yinelenen verilerle dolu olacak.

Ayrıca URI'leri, Adreslenebilirliği ve HTTP GET ve POST kullanımını da öneririm .


Bazı tarayıcılarda bağlantı önceden getirme konusunda da bir sorun var - bunlar sayfa yazarı tarafından belirtilmemiş olsa bile, getirme öncesi bağlantıları arayacaklar.

Oturumu kapattığınızda, sitenizdeki her sayfadan bağlantılı bir "GET" in arkasındaysa, bu davranış nedeniyle insanlar oturumu kapatabilir.


35
Pek çok, pek çok, pek çok araç, yardımcı program, web tarayıcısı ve diğer pek çok şey, GETbunun asla yıkıcı bir eylem olmayacağını varsayıyor (tam da bu şekilde belirtildiğinden beri). Şimdi bu şartnameyi ihlal ederek başvurunuzu kırarsanız, uygulamanızın her iki bölümünü de saklarsınız.
Joachim Sauer

7
@NimChimpsky: a ile değişiyor GET. Bu tavsiye sadece yanlıştır. Güvenli , kullanıcının yan etkilerden dolayı sorumlu tutulamaz, yan etkilerin olamayacağı anlamına gelir. Aksi halde, sunucunuz için günlük dosyalarına sahip olamazsınız, bu saçma olur! Bu, RFC2616'nın 9.1.1 bölümünde açıkça belirtilmiştir.
Jörg W Mittag

8
@ JörgWMittag: "Sadece yanlış" demem, "yanlış yazılmış ifadeler" derdim. Bir GET, hedefi olarak bir değişiklik olmamalıdır. Elbette bir GET isteğini saymanıza, kaydetmenize ve gözlemlemenize izin verilir. Ancak gerçek işletme verilerinizi değiştirmemelidir.
Joachim Sauer

23
@NimChimpsky A GET, tarafından istenen kaynağı değiştirmemelidir GET, ancak bu 'sunucudaki hiçbir şeyin değişmemesi' anlamına gelmez. Elbette, günlükler, sayaçlar ve diğer sunucu durumları gibi şeyler herhangi bir istek sırasında değişebilir.
Eric King,

8
Birkaç yıl önce, Google, sayfaları bağlantılar yoluyla getirebilecek bir tarayıcı eklentisi (iirc) yayınladı. Bu aynı zamanda kötü tasarlanmış bazı kontrol panellerinde de oldu - URL'ler sunucuda bir kaydın veya bir şeyin yazılmasına veya hatta silinmesine neden olur (post post? Action = delete). Bu, kullanıcının bilmeden eylemlerin gerçekleştirilmesine neden oldu. Google, bu nedenle, webapp üreticisinin durumu değiştirmek için GET’leri kullanması hatası olsa bile, bu eklentiyi iptal etti.
Cthulhu

24

Her HTTP fiilinin kendi sorumluluğu vardır. Örneğin GET, RFC tarafından tanımlandığı gibi

Talep-URI'sı ile tanımlanmış herhangi bir bilgiyi (bir varlık şeklinde) almak anlamına gelir.

POSTdiğer yandan, biçimsel olarak ya da daha fazla biçim vermek

POST yöntemi, kaynak sunucunun istekte bulunan
varlığı
İstek Satırında İstek URI'sı tarafından tanımlanan kaynağın yeni bir alt öğesi olarak kabul etmesini istemek için kullanılır

Bu şekilde tutmak için nedenler:

  • Çok basit ve 1991'den bu yana küresel İnternet ölçeğinde çalışıyor
  • Tek sorumluluk ilkesine sadık kalın
  • Diğer taraflar GETbilgi alma ve veri madenciliği aracı olarak hareket etmekte kullanılır
  • GET, hiçbir zaman kaynağın durumunu değiştirmeyen güvenli bir işlem olarak kabul edilir.
  • Güvenlik noktaları, GETetkili olan okuma , oysa POSTetkili olan yazma
  • GET tarayıcılar, ağdaki düğümler, İnternet Servis Sağlayıcıları tarafından önbelleğe alınır
  • İçerik değişmezse, GETaynı URL’nin tüm kullanıcılara aynı sonuçları döndürmesi gerekir, aksi halde geri döndürülen sonuçta bu şekilde bir güveniniz olmaz.

Bütünlüğü ve sadece doğru kullanımı zorlamak için (kaynak) :

  • GETParametreler, 4000'den fazla karakteri destekleyen bazı sunucularla, varsayılan olarak küçük ve sınırlı uzunluktaki 256 karakter uzunluğunda olan URL'nin bir parçası olarak iletilir. Uzun bir kayıt eklemek istiyorsanız, bu verileri içeri aktarmak için yasal bir yol yoktur.
  • Ne zaman kullanarak güvenli bağlantı, ̶ gibi TLS, ̶ URL da kalkmamak şifreli ̶ dolayısıyla her parametrelerin ̶ ̶G̶E̶T̶̶ devredilip düz metin. URL aslında TLS ile şifrelenmiştir, bu yüzden TLS iyidir.
  • Kullanarak ikili veri veya ASCII olmayan karakterler ekleme GETpratik değildir
  • GET Bir kullanıcı bir tarayıcıda Geri düğmesine basarsa yeniden yürütülür
  • Bazı eski tarayıcılar, ?içinde bir işaret bulunan URL’leri endekslemeyebilir

1
URL'nin TLS üzerinden şifrelenmediğinden emin misiniz? SSL / TLS el sıkışmalarının, aktarılan HTTP başlıklarından önce gerçekleştiği izlenimi altındaydım. Sanal HTTPS sitelerini tek bir IP adresi üzerinden barındırmanın zor olmasının nedeni budur. Yanılıyor muyum?
Brandon

Bu doğru, ben düzelttim
oleksii

2
@Brandon Modern tarayıcılar, IP adresi başına birden fazla alan barındırabilmesi için, ana bilgisayar alanını TLS anlaşmasının bir parçası olarak (sunucu adı göstergesi olarak bilinir) temiz olarak gönderir. URL'nin yol / sorgu kısmı TLS tarafından korunmaktadır. GET ile diğer HTTP fiilleri arasında bu konuda bir fark yoktur.
KodlarInChaos

9

EDIT: Daha önce POST'un CSRF'ye karşı korunmasına yardımcı olduğunu söyledim ama bu yanlış. Bunu doğru düşünmedim. CSRF'ye karşı koruma sağlamak amacıyla verileri değiştirmek için tüm isteklerinizde oturum kapsamı benzersiz bir gizli belirteç gerekir.

İnternetin ilk günlerinde tarayıcı hızlandırıcıları vardı. Bu programlar, içeriği önbelleğe almak için bir sayfadaki bağlantıları tıklamaya başlar. Google Web Accelerator bu programlardan biriydi. Bu, bir link tıklandığında değişiklik yapan bir uygulamaya zarar verebilir. Hızlandırıcı yazılımı kullanan hala insanlar olduğunu varsayardım.

Proxy sunucuları ve tarayıcılar, GET isteklerini önbelleğe alır, böylece kullanıcı sayfaya tekrar eriştiğinde, kullanıcının bir eylemde bulunduğunu düşünmesi için isteğinizi uygulamanıza göndermeyebilir, ancak gerçekten yapmadılar.


1
CSRF, GET ve POST ile aynı derecede mümkündür. Örneğin, saldırgan bir POST isteğini tetiklemek için sitelerinde otomatik gönderme formu içerebilir. CSRF'nin önlenmesine yönelik standart yaklaşım açıkça talepte saldırgan tarafından bilinmeyen bir değeri içerir (dolaylı olarak çerez başlıklarını içermez).
CodesInChaos,

8

Veritabanına veri ekleyen bir php servisi yaparsam ve onu GET sorgu dizgisine geçirirsem, neden bu yanlış?

En basit cevap " GETdemek istediğin değil çünkü" dır .

Kullanılması GET"- ŞİMDİ ACT ÖZEL TEKLİF!" Güncelleştirme için veri aktarmak için bir aşk mektubu yazma ve bir zarf içinde göndermeden gibidir işaretlenmiş Her iki durumda da, alıcı ve / veya aracıların mesajınızı yanlış yönlendirmesine şaşırmamalısınız .


5

Sizin için REZİL veritabanı merkezli uygulamada operasyonlarda şu şemayı kullanın:

Okuma İşlemleri için HTTP GET Kullan (SQL SELECT)

Güncelleme İşlemleri için HTTP PUT kullanın (SQL UPDATE)

İşlemler Oluşturmak için HTTP POST kullanın (SQL INSERT)

Silme İşlemleri için HTTP DELETE Kullan (SQL DELETE)


3
Put vs yazmayı belirttiğiniz gibi değil. Koymak, müşteri kaynağı tam olarak belirtilen yerde değiştirdiği zaman içindir. Bir gönderi için sunucu sonuçta kaynağın tam Uri'sine karar verir.
Andy,

HTTP PUT, UPDATE yerine bir SQL DELETE ve INSERT gibi değil mi? Ayrıca SQL UPDATE aynı anda birçok kaydı güncelleyebilir, ancak HTTP PUT yalnızca bir şeyi günceller.
Backwards_Dave

0

Bir GET hiçbir zaman sunucudaki verileri değiştirmemelidir; bunun için bir POST isteği kullanın.

Bu tavsiye ve buradaki tüm cevaplar yanlıştır. Açıkçası aşırı dramatik oluyorum, diğer cevaplar mükemmel, ancak kesin tavsiyenin şu şekilde verilmesi gerektiğine inanıyorum:

Bir GET sunucudaki verileri nadiren değiştirmeli - bunun için bir POST isteği kullanmalı

"Asla" demek çok aşırı değildir ve buradaki diğer cevaplar neden "nadiren" yapmanız gerektiğini doğru bir şekilde açıklasa da, verileri GET ile değiştirmenin gerçekten makul olduğu bazı senaryolar vardır. Örnek, bir defalık kullanım e-posta doğrulama bağlantısıdır. Genellikle bu bağlantılar, erişildiğinde verileri değiştirmek zorunda kalacak bir GUID içerir. Doğru şekilde uygulanırsa müteakip aynı GET istekleri göz ardı edilir.

Bu açıkça bir kenar davası ama kesinlikle kayda değer.


3
Mailclient bağlantınızı tıklamadan link almaya karar verirse? Örneğin, malware için taramak istediğinden. Abonelikten çıkma bağlantıları için doğru yaklaşım, kullanıcının aboneliği iptal etmek için bir düğmeyi tıklayabileceği bir sayfaya yönlendirmektir (düğmenin tıklatıldığı yer POST isteğini tetikler).
CodesInChaos,

@CodesInChaos - mükemmel nokta! Size katılıyorum. Abonelikten çıkma örneğini kaldırdım ve e-posta doğrulamasını tek örnek olarak bıraktım. Bir GET'in anlamlı olduğu yerde e-posta doğrulamanın yanı sıra başkaları da olabilir, ancak şu anda hiçbir şey düşünemiyorum.
TTT

GET'in yan etkilere sahip olması sorunu e-posta onayına eşit olarak uygulanır. Şimdi, bağlantıyı takip eden müşteri, e-postanızı kullanarak oluşturulmuş başka birinin hesabını onaylar ve sizi kimliğine bürünmelerini sağlar.
CodesInChaos

@CodesInChaos - bu bir esnemedir. Bahsettiğiniz kimliğe bürünme, aynı e-posta adresinden değil, aynı kullanıcı adından veya genel kişisel addan gelir ve bu, hangi e-posta adresini kullandıklarına bakılmaksızın gerçekleşebilir (genellikle yalnızca hesap sahibinin e-posta adresini bilir). Ayrıca, başkasının e-posta adresiyle bir hesap oluşturmak anlamsız olacaktır. Bu onlara nasıl yardımcı olabilir? Kendi hesaplarını kontrol edemediler.
TTT,
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.