सुपरग्लोब को सीधे संशोधित करना


20

मैंने लोगों को देखा है (जो आमतौर पर अच्छा कोड लिखते हैं) $_POSTइस तरह से कोड के साथ सरणी को सीधे बदल देते हैं :

// Add some value that wasn't actually posted
$_POST['last_activity'] = time();

// Alter an existing post value
$_POST['name'] = trim($_POST['name']);

// Our pretend function
// Pass the entire $_POST array as data to work with in the function
// The function update_record() will read only the values we actually need
update_record($_POST);

// ...That sure was easier than creating a new array 
//  with only the $_POST values we actually need.

यह समझ में आता है कि update_record()सीधे $ _POST का उपयोग नहीं करना चाहिए, इसलिए हम उदाहरण के लिए डेटा के अन्य सरणियों को पास कर सकते हैं, लेकिन निश्चित रूप से यह आलसी, खराब डिज़ाइन या संभवतः गलत है? हालाँकि, हम अभी भी एक मान्य सरणी पास कर रहे हैं update_record(), इसलिए एक नया निर्माण क्यों करें?

यह प्रश्न का बिंदु नहीं है, केवल उपयोग का एक उदाहरण है। हालांकि, मैंने बहुत से लोगों को यह कहते सुना है कि यह $_REQUESTडेटा के साथ नहीं किया जाना चाहिए , और यह बुरा अभ्यास है। लेकिन क्यों? हानिरहित पर्याप्त दिखता है।

उदाहरण:

  • डिफ़ॉल्ट $_GET(या पोस्ट) मान सेट करना जो वास्तव में मौजूद नहीं है

  • उन $_POSTमानों को जोड़ना जो वास्तव में एक फॉर्म सबमिशन के बाद पोस्ट नहीं किए गए थे

  • स्क्रिप्ट में बहुत जल्दी $_GETसरणी मानों या कुंजियों को सीधे साफ़ करना या फ़िल्टर करना (फ़ॉलबैक सैनिटेशन ... क्यों नहीं?)

  • $_POSTकिसी इनपुट को डिफ़ॉल्ट मान के साथ जमा करने के लिए फ़ॉर्म सबमिट करने से पहले मैन्युअल रूप से सेट करना (जब इनपुट $_POSTडिफ़ॉल्ट मान के लिए पढ़ता है ; मैंने ऐसा किया है)

  • अपने स्वयं के $_SERVERमूल्यों को बनाना ? ज़रूर, अरे क्यों नहीं?

  • कैसे दूसरों के बारे में, पसंद है $_COOKIEऔर $_SESSION? निश्चित रूप से हमें उन लोगों को सीधे तौर पर संशोधित करना होगा? फिर दूसरे क्यों नहीं?

सुपरग्लोबल्स का प्रत्यक्ष संशोधन कभी नहीं किया जाना चाहिए, या क्या कुछ उदाहरणों में ऐसा करना ठीक है ?


मैं # 1, # 2 और # 3 से सहमत हूं क्योंकि यह अप्रत्याशित उपयोग है (विशेषकर # 1 और # 2)।
केविन पेनो

अच्छा प्रश्न। वैश्विक सरणियों को संशोधित करना उसी तरह गलत है जैसे वैश्विक मूल्यों का उपयोग करना गलत है। इसके अलावा इन सरणियों का अपना उद्देश्य (बाहर से पैरामीटर पारित करना) है जो कोड के भीतर गड़बड़ करने के लिए उन्हें सीधे तरीके से बदल देता है। लेकिन, मेरा मानना ​​है कि इनमें से कुछ सरणियों को स्क्रिप्ट के भीगने पर साफ किया जा सकता है, बस कोड के भीतर समस्या पैदा करने के लिए नहीं।
ताडेक

1
मैं OO इनपुट ऐरे रैपर (अंतर्निहित फ़िल्टरिंग) का उपयोग कर रहा हूं, जो $ _GET या $ _POST चर के साथ छेड़छाड़ होने पर एक अतिरिक्त सूचना प्रिंट करता है। यह अभी भी संभव है, लेकिन संकीर्ण परिस्थितियों के लिए विवश होना चाहिए। (क्रॉस-मॉड्यूल सिग्नलिंग, केवल डिस्पैचर / फ्रंट कंट्रोलर को इसकी आवश्यकता होनी चाहिए।)
mario

@ उमरियो: मुझे यह सुनने में अच्छा लगेगा कि आपने इसे कैसे पूरा किया है कि यदि आप इस प्रश्न पर एक नज़र डाल सकते हैं: stackoverflow.com/questions/12954656
वेस्ले मर्च

जवाबों:


16

यह देखते हुए कि PHP पहले से ही उन सुपरग्लोब को सेट कर रहा है, मुझे नहीं लगता कि उन्हें संशोधित करना बुरा है। कुछ मामलों में, यह समस्याओं को हल करने का सबसे अच्छा तरीका हो सकता है ... खासकर जब तीसरे पक्ष के कोड से निपटना जो आप आसानी से संशोधित नहीं कर सकते। (वे $_GETसीधे उपयोग कर सकते हैं या मान सकते हैं कि कुछ कुंजी मौजूद है $_SERVER, आदि)

हालांकि, आम तौर पर बोलते हुए, मुझे लगता है कि यह एक बुरा अभ्यास है जब आप अपना कोड लिख रहे हैं। $_REQUESTप्रत्येक पृष्ठ पर स्वचालित रूप से चलने वाले पर्दे के पीछे कुछ डेटा के साथ डेटा को संशोधित करने से दुष्प्रभाव होने की संभावना है। (सबूत के लिए "जादू कोट्स" के कारण सभी समस्याएं देखें।)

इसलिए यदि आप ऐसा नहीं करने जा रहे हैं (स्वचालित रूप से सुपरग्लोब फ़िल्टर करें), तो निम्नलिखित आपको कोई लाभ नहीं देते हैं:

$_POST['foo'] = filter($_POST['foo']);

जब आप आसानी से बस कर सकते हैं:

$foo = filter($_POST['foo']);

मुझे लगता है कि यह है कि साइट चौड़ा अंतर बनाने के लिए और अधिक स्पष्ट है $_POSTऔर $_GETकर रहे हैं हमेशा फ़िल्टर नहीं किए गए, अविश्वसनीय डेटा, और वे चाहिए कभी नहीं के रूप में इस्तेमाल किया जा रहा है।

फ़िल्टर किए गए मान को दूसरे चर पर कॉपी करके, आप यह दावा कर रहे हैं कि, "मैं समझता हूं कि मैं क्या कर रहा हूं ... मैंने इस इनपुट को फ़िल्टर कर दिया है, और यह उपयोग करने के लिए सुरक्षित है।"


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

1
@Wesley, इसका मुख्य कारण "बुरा" है, यह बहुत अधिक संभावना है कि आप कुछ उपयोगकर्ता डेटा को पवित्रा करना भूल जाएंगे। अपने उदाहरण में, आप एक कुंजी को संशोधित करते हैं, फिर पूरे सरणी को पास करते हैं। क्या होगा अगर उस डेटा में से कुछ में दुर्भावनापूर्ण इनपुट है जो संसाधित नहीं है? हाथ से उस नए सरणी को बनाने के लिए बेहतर है, केवल आपके द्वारा इसमें जाने वाली चीजों को कॉपी $_POSTकरना, जैसे आप साथ जाते हैं। और ऐसा करने वाले अन्य लोगों के बारे में ... अच्छी तरह से, बहुत से लोग बहुत खराब PHP कोड लिखते हैं, लेकिन यह आपके लिए भी कोई बहाना नहीं है। :)
कोनफोर्स

मुझे लगता है कि मुझे सिर्फ सैनिटाइजिंग डेटा के अलावा सुपरग्लोबल्स दुरुपयोग के अन्य अनुप्रयोगों पर जोर देना चाहिए था। मुझे संभवतः इसे पूरी तरह से छोड़ देना चाहिए था और एक स्पष्ट प्रश्न लिखा था, लोग विशेष रूप से सुरक्षा पहलुओं पर उठाते हैं और अक्सर बाकी की उपेक्षा करते हैं। कृतघ्न ध्वनि करने के लिए नहीं, मैं वास्तव में प्रतिक्रिया की सराहना करता हूं। मैं एक दिन प्रतीक्षा करने जा रहा हूं और इसे एक चेक मार्क दे रहा हूं, जैसा कि आपने कुछ अच्छे बिंदुओं को संबोधित किया है, लेकिन 3 मिनट के दौरान वोटिंग पार्टी को याद किया जब प्रश्न नया था :) फिर से धन्यवाद!
वेस्ले मर्च

9

मैं आमतौर पर सुझाव दूंगा कि आपको पूर्व-परिभाषित सुपर-ग्लोबल्स को संशोधित नहीं करना चाहिए ताकि यह स्पष्ट हो जाए कि स्वच्छता डेटा क्या है और कच्चा / अविश्वसनीय डेटा क्या है।

दूसरों का सुझाव हो सकता है कि यदि आप अनुरोध चक्र की शुरुआत में सुपरग्लोबल्स को साफ करते हैं तो आपको उनके बारे में कहीं और चिंता करने की आवश्यकता नहीं है।

जब आपको उनकी आवश्यकता हो तो मैं हमेशा उनका मिलान करूंगा:

$id = (int)$_POST['id'];

या इसी के समान।

अन्य चर के संदर्भ में यह अच्छा अभ्यास के लिए नहीं में से किसी को लिखना है $_GET, $_POST, $_REQUEST, $_SERVERया $_COOKIE$_SESSIONहालाँकि यह अलग है क्योंकि आप अक्सर सत्र में डेटा लिखना चाहते हैं जो तब सत्र में विभिन्न अनुरोधों पर कायम रहता है।


2
अधिक कारण है कि इस प्रकार के ग्लोबल्स को उन वस्तुओं / विधियों से प्रतिस्थापित किया जाना चाहिए जिन्हें आवश्यक होने पर उन्हें प्राप्त करने के लिए कहा जा सकता है। क्यों setcookieमौजूद है, लेकिन हम कुकीज़ प्राप्त करते हैं $_COOKIE? इसके अलावा, चूंकि $_COOKIEकेवल वर्तमान सत्र शुरू होने पर ही सेट किया जाता है, और कभी भी अपडेट नहीं किया जाता है, इसके लिए आवश्यक है कि आप दोनों क्षेत्रों में कुकीज़ को बदल दें / सेट करें, ताकि बाद में कोड के क्षेत्रों की जानकारी हो।
केविन पेनो

धन्यवाद जेम्स, मैं थोड़ी देर के लिए ऑफ़लाइन हो गया हूं इसलिए मैं प्रतिक्रिया नहीं दे सका। एक लंबी कहानी को छोटा करने के लिए - मैं आपसे सहमत हूँ। पोस्ट लिखने / पाने / इत्यादि से हमेशा बेहतर समाधान होता है, लेकिन मुझे अभी भी यकीन नहीं है कि यह एक कड़ाई से बुरा विचार है, जैसा कि " कभी भी ऐसा न करें "। इसलिए, यदि मैं इस प्रकार के कोड को फिर से आता हूं, तो क्या आपको लगता है कि मुझे मैला कोड पर "उन्हें कॉल आउट" करने का अधिकार है, या कभी-कभी यह एक चतुर, सुरक्षित तरीके से उपयोग किया जा सकता है?
वेस्ले मर्च

@Wesley अगर यह "कभी ऐसा नहीं करेगा" तो सुपरग्लोब शायद ही कड़ाई से पढ़े-लिखे होंगे - वे नहीं हैं। मैं सिर्फ इसे अपने आवेदन कोड में सेट या ओवरराइट करने के लिए बुरा व्यवहार कहूंगा - उक्त कारणों से।
मिशेल फेल्डहाइम

3

आपको इससे बचना चाहिए। हो सकता है कि कुछ समय के बाद आप कुछ साफ करना भूल गए, तो आप खतरनाक डेटा को पुनः प्राप्त कर सकते हैं। यदि आप डेटा को सैनिटाइज़ करते समय एक नई संरचना में कॉपी करते हैं

  • आपको केवल वही मिलता है, जो आप चाहते हैं / जरूरत है और नहीं $_POSTभी है
  • आप शायद एक त्रुटि प्राप्त करेंगे, अगर नव निर्मित सरणी कुछ चाबियाँ गायब है या बिल्कुल गायब है

अतिरिक्त अन्य स्क्रिप्ट मान सकते हैं, कि सरणी अछूता है और उत्सुक प्रतिक्रिया दे सकता है।


2

मुझे सुपरग्लोबल को संशोधित करने का विचार कभी पसंद नहीं आया क्योंकि यह भ्रामक है। यह कुछ करने के लिए एक त्वरित हैकी तरीका है कि लगभग एक बेहतर तरीका होने की संभावना है।

यदि आप $_POSTउदाहरण के लिए, का मान बदलते हैं , तो आप कह रहे हैं कि सॉफ़्टवेयर को डेटा प्राप्त हुआ जो उसने नहीं किया।

वास्तविक समस्या

एक वास्तविक जीवन की स्थिति है जहाँ यह एक बड़ी समस्या बन जाती है:

कल्पना कीजिए कि आप एक टीम में काम कर रहे हैं। एक आदर्श दुनिया में, हर कोई एक ही वाक्य रचना का उपयोग करता है, लेकिन हम एक आदर्श दुनिया में नहीं रहते हैं। एक डेवलपर, जॉन, पोस्टेड डेटा का उपयोग करना पसंद करता है $_POST। वह पोस्ट संस्करण में कुछ बदलता है:

$_POST['ranking'] = 2; // John has changed ranking from 1 to 2 for whatever reason

फिर आपके पास एक और डेवलपर क्रिस है, जो filter_inputइनपुटेड (यानी GET, POST, SERVER, COOKIE) डेटा का उपयोग करने के लिए उपयोग करना पसंद करता है क्योंकि यह सॉफ्टवेयर की सुरक्षा के लिए जाता है जब डेटा से छेड़छाड़ करता है ताकि उपयोगकर्ता छेड़छाड़ कर सके। सॉफ्टवेयर के अपने हिस्से में, उसे पोस्ट वैल्यू पाने की जरूरत है ranking। कोड का उनका हिस्सा AFTER John's है।

$ranking = filter_input(INPUT_POST, 'ranking', FILTER_SANITIZE_NUMBER_INT);
// $ranking = 1

ऊपर के उदाहरण से, एक सुपरग्लोबल को बदलकर, आपने PHP को तोड़ दिया है। जॉन ने $_POST['ranking']किसी भी कारण से 2 का मान निर्धारित किया है , लेकिन अब क्रिस को 1 का मान मिला है

जब मैंने इसे करने का कोई अन्य तरीका नहीं देखा:

मैंने एक ऐसी परियोजना पर काम किया, जिसने AWS लोड-बैलेंसर के पीछे अपने ब्लॉग के रूप में वर्डप्रेस का उपयोग किया। यह का मान बदलता है $_SERVER['remote_address']। इस उदाहरण में, अन्य डेवलपर के पास निम्नलिखित कार्य करने के अलावा कोई विकल्प नहीं था:

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $parts = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
    $_SERVER['REMOTE_ADDR'] = $parts[0];
}

निष्कर्ष

सुपरग्लोबल्स को बदलने की तुलना में लगभग निश्चित रूप से एक बेहतर तरीका है


1

मुझे लगता है कि यहां असली सवाल यह है कि "आपको विषय को क्यों बदलना चाहिए?"। मुझे ऐसा करने का कोई वैध कारण नहीं दिखता। यदि आपको एक अशुद्ध वस्तु को पवित्र करने की आवश्यकता है, तो आप एक स्थानीय चर का उपयोग करना चाह सकते हैं ...

जब तक आप कोड पर्याप्त नहीं होते हैं (कहते हैं, 50 लाइनों से कम लंबी), उन सुपर-ग्लोबल को संशोधित करना केवल आपके कोड को बनाए रखने और अंडरस्कोर करने के लिए कठिन बना देगा।

वैसे, आपको फ़ंक्शन के लिए $ _POST पास करने की आवश्यकता नहीं है, क्योंकि यह एक सुपरग्लोबल सरणी है जो किसी फ़ंक्शन के स्थानीय दायरे में भी एक्सेस किया जा सकता है।


3
लेकिन उसे पास करना चाहिए । परीक्षण करने के लिए बहुत कठिन है और किसी भी (यहां तक ​​कि बदसूरत) हैक्स के बिना अन्य मूल्यों के साथ फ़ंक्शन / विधि को कॉल करना संभव नहीं है
KingCrunch

खैर, यह इस बात पर निर्भर करता है कि उसका तरीका क्या है। यदि इसे केवल $ _POST सरणी पर पार्स करने के लिए डिज़ाइन किया गया है, तो उसे पास करने की आवश्यकता नहीं है। बेशक, अगर यह अधिक सामान्य / सार उद्देश्य की सेवा करता है, तो आप सही हैं।

2
@ तोमास, मैं यहाँ राजा से सहमत हूँ। यहां तक ​​कि अगर वे वैश्विक हैं, तो आपको अन्य स्कोप के भीतर वैश्विक चीज़ों का उपयोग नहीं करना चाहिए क्योंकि यह तंग युग्मन का कारण बनता है (यही कारण है कि फ़ंक्शन का पुन: उपयोग नहीं किया जा सकता है)। आपके उदाहरण को देखते हुए, यदि फ़ंक्शन डेटा को सैनिटाइज़ करना है, तो यह केवल डेटा को सैनिटाइज़ क्यों करता है $_POST? $_POSTफ़ंक्शन में पासिंग किसी भी डेटा को सैनिटाइज़ करता है।
केविन पेनो

0

शुरू में इस प्रश्न का उत्तर देने के बाद यह कहने के लिए कि सुपरग्लोबल्स को संशोधित करने का कोई कारण नहीं होना चाहिए, मैं इस उत्तर को उस समय के उदाहरण के साथ संपादित कर रहा हूं जब मैंने निर्णय लिया है।

मैं वर्तमान में एक URL फिर से डेटाबेस टेबल पर काम कर रहा हूँ जिसके द्वारा request कॉलम उपयोगकर्ता को अपने संबंधित targetकॉलम में निर्देशित करता है।

उदाहरण के लिए, ए request हो सकता है blog/title-hereऔर यह targetहो सकता है blog.php?id=1

चूंकि चर blog.phpकी उम्मीद $_GETहै, और मैं इसे बदलना नहीं चाहताheader("Location:") , इसलिए मैं कुछ ऐसा कर रहा हूँ:

$uri    = explode('?', $uri_request)[0];
$params = explode('?', $uri_request)[1];
parse_str($params, $_GET);

यह एक बनाता है $_GET सरणी जिसमें targetस्तंभ द्वारा पारित किए गए इच्छित पैरामीटर हैं ।

अंत में, मैं सुपरग्लोबल्स को संशोधित करने के खिलाफ दृढ़ता से सलाह दूंगा जब तक कि आपके पास बिल्कुल न हो

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.