सर्वर पर डेटा बदलने का अनुरोध क्यों नहीं करना चाहिए?


109

पूरे इंटरनेट पर, मुझे निम्नलिखित सलाह दिखाई देती है:

एक GET सर्वर पर डेटा को कभी नहीं बदलना चाहिए- उसके लिए एक POST अनुरोध का उपयोग करें

इस विचार का आधार क्या है?

यदि मैं एक php सेवा बनाता हूं जो डेटाबेस में डेटा सम्मिलित करता है, और इसे GET क्वेरी स्ट्रिंग में पैरामीटर पास करता है, तो यह गलत क्यों है? (मैं एसक्यूएल इंजेक्शन की देखभाल के लिए तैयार किए गए बयानों का उपयोग कर रहा हूं)। क्या किसी तरह से POST अनुरोध अधिक सुरक्षित है?

या इसकी कोई ऐतिहासिक वजह है? यदि हां, तो यह सलाह आज कितनी वैध है?




इस प्रश्न को पूछने के लिए धन्यवाद, और धन्यवाद @ अच्छी तरह से पूछे गए उत्तर के लिए @ मुझे हमेशा उन लोगों को भेजने के लिए एक संदर्भ की आवश्यकता है जो इस प्रश्न को :) के लिए भेजते हैं
बेंजामिन ग्रुएनबाउम

इसके अलावा HTTP PUT - stackoverflow.com/questions/630453/put-vs-post-in-rest (आईडीपोटेंट होने के बारे में नोटों के साथ) देखें
Bratch

2
@JoachimSauer जबकि GET ने उन्हें क्रॉलर से बचाया होगा, मूल समस्या प्रमाणीकरण की कमी थी। कोई भी स्क्रिप्ट अपहरण उन्हें गुमनामी में भी पोस्ट कर सकता था।
कोडइन्चोस

जवाबों:


185

यह सलाह नहीं है।

HTTP प्रोटोकॉलGET में A को इस तरह से परिभाषित किया गया है । यह माना जाता है idempotent और सुरक्षित

क्यों के लिए - GETताज़ा किया जा सकता है और एक ब्राउज़र में कैश किया जा सकता है। ओवर एंड ओवर एंड ओवर।

इसका मतलब है कि यदि आप GETफिर से वही बनाते हैं , तो आप अपने डेटाबेस में फिर से डालेंगे

इस बात पर विचार करें कि यदि GETलिंक बन जाता है तो इसका क्या मतलब हो सकता है और यह एक खोज इंजन द्वारा क्रॉल हो जाता है। आपके पास अपना डेटाबेस डुप्लिकेट डेटा से भरा होगा।

मेरा सुझाव है कि आप यूआरआई, एड्रेसबिलिटी, और HTTP जीईटी और पोस्ट का उपयोग करें


कुछ ब्राउज़रों में लिंक प्रीफ़ेटिंग के साथ एक समस्या भी है - वे पूर्व-लिंक लिंक को कॉल करेंगे, भले ही पृष्ठ लेखक द्वारा ऐसा संकेत न दिया गया हो।

यदि कहें, तो आपका लॉग आउट एक "जीईटी" के पीछे है, जो आपकी साइट के प्रत्येक पृष्ठ से जुड़ा हुआ है, लोग इस व्यवहार के कारण लॉग आउट कर सकते हैं।


35
कई, कई, कई उपकरण, उपयोगिताओं, वेब क्रॉलर और अन्य चीज़मजिग्गीज़ मान लेते हैं कि GETयह कभी भी विनाशकारी कार्रवाई नहीं होगी (ठीक है इसलिए, क्योंकि यह इस तरह से निर्दिष्ट है)। यदि आप अब उस विनिर्देशन को तोड़कर अपना आवेदन करते हैं, तो आपको अपने आवेदन के दोनों हिस्सों को रखना होगा।
जोआचिम सौएर

7
@NimChimpsky: यह ए द्वारा बदला जाता है GET। वह सलाह बस गलत है। सुरक्षित का मतलब है कि उपयोगकर्ता को साइड-इफेक्ट के लिए जवाबदेह नहीं ठहराया जा सकता है, न कि यह कि साइड-इफेक्ट नहीं हो सकते। अन्यथा आप अपने सर्वर के लिए लॉग फाइल नहीं कर सकते हैं, जो बेतुका होगा! यह RFC2616 की धारा 9.1.1 में स्पष्ट रूप से लिखा गया है।
जोर्ग डब्ल्यू मित्तग

8
@ JörgWMittag: मैं "बस गलत" नहीं कहूंगा, मैं कहूंगा कि "पूरी तरह से अक्षम"। GET में परिवर्तन नहीं होना चाहिए क्योंकि यह लक्ष्य है। बेशक, आपको एक GET अनुरोध को गिनने, लॉग इन करने और निरीक्षण करने की अनुमति है। लेकिन यह आपके वास्तविक व्यावसायिक डेटा को संशोधित नहीं करना चाहिए।
जोआचिम सॉर

23
@NimChimpsky A GETको संसाधन द्वारा अनुरोध किए गए परिवर्तन को नहीं बदलना चाहिए GET, लेकिन इसका मतलब यह नहीं है कि 'सर्वर पर कुछ भी नहीं बदलना चाहिए'। बेशक किसी भी अनुरोध के दौरान लॉग, काउंटर और अन्य सर्वर स्थिति जैसी चीजें बदल सकती हैं।
एरिक किंग

8
कुछ साल पहले, Google ने एक ब्राउज़र ऐड-ऑन (iirc) जारी किया था जो लिंक के माध्यम से पृष्ठों को पहले से लाएगा। यह कुछ नियंत्रण पैनलों पर भी हुआ था जो खराब तरीके से डिजाइन किए गए थे - यूआरएल एक रिकॉर्ड या कुछ लिखने या यहां तक ​​कि सर्वर पर हटाए जाने का कारण बन जाएगा (विचार पोस्ट? कार्रवाई = हटाएं)। इसके कारण उन कार्यों को अंजाम दिया जा सकता है जो उपयोगकर्ता इसे जाने बिना करता है। Google ने उस कारण के लिए addon को बंद कर दिया, iirc, भले ही वह GET का उपयोग करके राज्य बदलने के लिए वेब निर्माता की गलती थी।
15:33 पर Cthulhu

24

प्रत्येक HTTP क्रिया की अपनी जिम्मेदारी है। उदाहरण के लिए GET, जैसा कि आरएफसी द्वारा परिभाषित किया गया है

अनुरोध-URI द्वारा पहचानी गई किसी भी जानकारी (एक इकाई के रूप में) को पुनः प्राप्त करना।

POSTदूसरी ओर, का अर्थ है सम्मिलित करना या अधिक औपचारिक रूप से

POST विधि का उपयोग अनुरोध करने के लिए किया जाता है कि मूल सर्वर
अनुरोध में संलग्न इकाई
को अनुरोध-लाइन में अनुरोध-यूआरआई द्वारा पहचाने गए संसाधन के नए अधीनस्थ के रूप में स्वीकार करता है

इसे इस प्रकार रखने के कारण:

  • यह बहुत सरल है और 1991 से वैश्विक इंटरनेट पैमाने पर काम करता है
  • एकल जिम्मेदारी सिद्धांत के लिए छड़ी
  • अन्य पक्ष GETसूचना पुनर्प्राप्ति और डेटा खनन के माध्यम के रूप में कार्य करने के लिए उपयोग करते हैं
  • GET को एक सुरक्षित संचालन माना जाता है जो संसाधन की स्थिति को कभी भी संशोधित नहीं करता है
  • सुरक्षा विचार, GETप्रभावी रूप से पढ़ा जाता है , जबकि POSTप्रभावी रूप से एक लेखन है
  • GET को ब्राउज़र, नेटवर्क में नोड्स, इंटरनेट सर्विस प्रोवाइडर्स द्वारा कैश किया जाता है
  • जब तक सामग्री नहीं बदलती है, तब तक एक GETही URL को सभी उपयोगकर्ताओं के लिए एक ही परिणाम वापस करना होगा या फिर आपको कोई भरोसा नहीं होगा कि लौटे परिणाम में कभी ऐसा क्या है

पूर्णता और केवल सही उपयोग (स्रोत) लागू करने के लिए :

  • GETपैरामीटर URL के हिस्से के रूप में पारित किए जाते हैं, जो डिफ़ॉल्ट रूप से 256 वर्णों की छोटी और सीमित लंबाई के होते हैं, कुछ सर्वर 4000+ वर्णों का समर्थन करते हैं। यदि आप एक लंबा रिकॉर्ड सम्मिलित करना चाहते हैं, तो इस डेटा को पास करने का कोई वैध तरीका नहीं है
  • का उपयोग करते समय सुरक्षित कनेक्शन, ̶ जैसे टीएलएस, ̶ यूआरएल है नहीं मिल रहा है एन्क्रिप्टेड, ̶ इसलिए सभी मापदंडों के ̶ ̶G̶E̶T̶̶ हैं हस्तांतरित सादा पाठ। URL टीएसएस के साथ एन्क्रिप्टेड है, इसलिए टीएलएस ठीक है।
  • द्विआधारी डेटा या गैर-एएससीआईआई अक्षरों का उपयोग GETकरना अव्यावहारिक है
  • GET यदि उपयोगकर्ता किसी ब्राउज़र में बैक बटन दबाता है तो उसे फिर से निष्पादित किया जाता है
  • कुछ पुराने क्रॉलर URL को ?अंदर साइन के साथ अनुक्रमित नहीं कर सकते हैं

1
क्या आप सुनिश्चित हैं कि URL TLS पर अनएन्क्रिप्टेड है? मैं इस धारणा के तहत था कि एसएसएल / टीएलएस हैंडशेक HTTP हेडर को स्थानांतरित करने से पहले होते हैं। यही कारण है कि एक एकल आईपी पते पर एचटीटीपीएस साइटों की वर्चुअल होस्टिंग मुश्किल है। क्या मैं गलत हूं?
ब्रैंडन

यह सही है, मैंने इसे ठीक किया
ओलेक्सी

2
@ ब्रैंडन मॉडर्न ब्राउज़र होस्ट डोमेन को TLS हैंडशेक (सर्वर नेम इंडिकेशन के रूप में जाना जाता है) के हिस्से के रूप में स्पष्ट रूप से भेजते हैं, जिससे प्रति आईपी एड्रेस एक से अधिक डोमेन को होस्ट करने की अनुमति मिलती है। Url का पथ / क्वेरी भाग TLS द्वारा सुरक्षित है। उस संबंध में GET और अन्य HTTP क्रियाओं के बीच कोई अंतर नहीं है।
कोडइन्चौस

9

EDIT: इससे पहले, मैंने कहा कि POST आपको CSRF से बचाने में मदद करता है लेकिन यह गलत है। मैंने इसके बारे में सही तरीके से नहीं सोचा। CSRF से सुरक्षा के लिए डेटा बदलने के लिए आपको अपने सभी अनुरोधों में एक सत्र-स्कोप अद्वितीय छिपे हुए टोकन की आवश्यकता होगी।

इंटरनेट के शुरुआती दिनों में ब्राउज़र एक्सेलेरेटर थे। ये कार्यक्रम सामग्री को कैश करने के लिए एक पृष्ठ पर लिंक पर क्लिक करना शुरू कर देंगे। Google वेब त्वरक इनमें से एक कार्यक्रम था। यह एक आवेदन पर कहर बरपा सकता है जो लिंक पर क्लिक करने पर परिवर्तन करता है। मैं यह धारणा बनाऊंगा कि अभी भी त्वरक सॉफ्टवेयर का उपयोग करने वाले लोग हैं।

प्रॉक्सी सर्वर और ब्राउजर GET रिक्वेस्ट को कैश कर देंगे, ताकि जब यूजर पेज को दोबारा एक्सेस करे तो हो सकता है कि वह आपके एप्लिकेशन को रिक्वेस्ट न भेजे इसलिए यूजर को लगता है कि उन्होंने एक्शन लिया है, लेकिन उन्होंने वास्तव में ऐसा नहीं किया।


1
CSRF GET और POST के साथ समान रूप से संभव है। उदाहरण के लिए हमलावर POST अनुरोध को ट्रिगर करने के लिए अपनी साइट पर एक ऑटो-सबमिट फॉर्म शामिल कर सकते हैं। CSRF को रोकने के लिए मानक दृष्टिकोण स्पष्ट रूप से अनुरोध में हमलावर के लिए एक मूल्य अज्ञात है (विपरीतार्थक कुकी हेडर शामिल हैं)।
कोडइन्चोज

8

यदि मैं एक php सेवा बनाता हूं जो डेटाबेस में डेटा सम्मिलित करता है, और इसे GET क्वेरी स्ट्रिंग में पैरामीटर पास करता है, तो यह गलत क्यों है?

सबसे सरल उत्तर है "क्योंकि GETइसका मतलब यह नहीं है।"

GETएक अद्यतन के लिए डेटा पास करने के लिए उपयोग करना एक प्रेम पत्र लिखने और एक लिफाफे में "विशेष प्रस्ताव - अधिनियम अब!" दोनों ही मामलों में, आपको प्राप्तकर्ता को आश्चर्यचकित नहीं करना चाहिए और / या बिचौलिये आपके संदेश को गलत तरीके से पेश करते हैं


5

डेटाबेस-केंद्रित अनुप्रयोग में अपने CRUD संचालन के लिए निम्न स्कीमा का उपयोग करें:

पढ़ें संचालन के लिए HTTP GET का उपयोग करें (SQL चयन)

अपडेट ऑपरेशंस के लिए HTTP PUT का उपयोग करें (SQL UPDATE)

क्रिएट ऑपरेशन्स के लिए HTTP POST का उपयोग करें (SQL INSERT)

डिलीट ऑपरेशंस के लिए HTTP DELETE का उपयोग करें (SQL DELETE)


3
पुट बनाम पोस्ट आप के अनुसार नहीं है। पुट तब के लिए है, जब ग्राहक दिए गए स्थान पर संसाधन को संशोधित कर रहा है। एक पद के लिए सर्वर अंततः संसाधन के लिए सटीक उड़ी तय करता है।
एंडी

क्या HTTP अद्यतन के बजाय SQL DELETE और INSERT की तरह HTTP PUT नहीं है? इसके अलावा SQL UPDATE एक साथ कई रिकॉर्ड अपडेट कर सकता है, लेकिन HTTP PUT केवल एक ही चीज़ को अपडेट करेगा।
पश्चगामी_

0

एक GET सर्वर पर डेटा को कभी नहीं बदलना चाहिए- उसके लिए एक POST अनुरोध का उपयोग करें

वह सलाह, और यहाँ सभी उत्तर गलत हैं। जाहिर है मैं अत्यधिक नाटकीय हो रहा हूं, अन्य उत्तर उत्कृष्ट हैं, लेकिन मेरा मानना ​​है कि सटीक सलाह इस प्रकार दी जानी चाहिए:

जीईटी को सर्वर पर डेटा को शायद ही कभी बदलना चाहिए- उसके लिए एक पोस्ट अनुरोध का उपयोग करें

"कभी नहीं" कहने के लिए बहुत चरम है, और यद्यपि यहां अन्य उत्तर सटीक रूप से समझाते हैं कि आपको "शायद ही कभी" ऐसा क्यों करना चाहिए, कुछ परिदृश्य हैं जहां जीईटी के साथ डेटा बदलना पूरी तरह से उचित है। एक उदाहरण एक बार उपयोग ईमेल सत्यापन लिंक है। आमतौर पर इन लिंक में एक GUID होता है जिसे एक्सेस करने पर डेटा बदलना होगा। यदि बाद में समान GET अनुरोधों को सही ढंग से कार्यान्वित किया जाता है तो इसे अनदेखा कर दिया जाएगा।

यह स्पष्ट रूप से एक किनारे का मामला है, लेकिन निश्चित रूप से ध्यान देने योग्य है।


3
क्या होगा यदि आपका मेलक्लिंक उस पर क्लिक किए बिना लिंक लाने का निर्णय लेता है? उदाहरण के लिए क्योंकि यह मैलवेयर के लिए इसे स्कैन करना चाहता है। अनसब्सक्राइब लिंक के लिए उचित दृष्टिकोण एक ऐसे पेज की ओर ले जाता है, जहां उपयोगकर्ता अनसब्सक्राइब करने के लिए एक बटन पर क्लिक कर सकता है (जहां बटन क्लिक पोस्ट को ट्रिगर करता है)।
कोडइन्चोस

@CodesInChaos - उत्कृष्ट बिंदु! मैं आपसे सहमत हुँ। मैंने सदस्यता समाप्त करने वाले उदाहरण को हटा दिया है और ईमेल सत्यापन को एकमात्र उदाहरण के रूप में छोड़ दिया है। ईमेल सत्यापन के अलावा कुछ अन्य भी हो सकते हैं जहां एक GET का अर्थ होता है, लेकिन मैं इस समय किसी के बारे में नहीं सोच सकता।
TTT

जीईटी के साइड इफेक्ट होने की समस्या ईमेल की पुष्टि पर समान रूप से लागू होती है। अब लिंक का अनुसरण करने वाला ग्राहक आपके ईमेल का उपयोग करके बनाए गए किसी खाते की पुष्टि करेगा, जिससे वे आपको प्रतिरूपित कर सकेंगे।
कोडइन्चोस

@CodesInChaos - कि एक खिंचाव है। आपके द्वारा बोला गया प्रतिरूपण एक ही उपयोगकर्ता नाम या सार्वजनिक व्यक्तिगत नाम से आएगा, न कि एक ही ईमेल पते से, और यह इस बात पर ध्यान दिए बिना हो सकता है कि वे किस ईमेल पते का उपयोग करते हैं (आमतौर पर केवल सर्वर को खाता धारक का ईमेल पता वैसे भी पता होता है)। इसके अलावा, किसी अन्य व्यक्ति के ईमेल पते के साथ खाता बनाना व्यर्थ होगा। यह कैसे उनकी मदद कर सकता है? वे अपने स्वयं के खाते को नियंत्रित नहीं कर सके।
TTT
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.