5

ठीक है, मुझे अभी भी वास्तव में यह नहीं मिलता है। मैं पढ़ रहा हूं कि अपने MySQL क्वेरी से ठीक से बचने के लिए, आपको mysqli_prepare() और mysqli_bind_param() का उपयोग करने की आवश्यकता है।क्या कोई स्पष्ट रूप से समझा सकता है कि mysqli_prepare()/bind_param() real_escape_string() से बेहतर क्यों है?

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

मुझे लगता है कि मैं सिर्फ क्या अंतर के बीच है नहीं मिलता है:

<?php 
$sql = new \MySQLi(...); 
$result = $sql->query(' 
    UPDATE `table` 
    SET 
     `field` = "'.$sql->real_escape_string($_REQUEST[$field]).'"; 
'); 
?> 

और

<?php 
$sql = new \MySQLi(...); 
$stmt = $sql->prepare(' 
    UPDATE `table` 
    SET 
     `field` = ?; 
'); 
$value = $_REQUEST[$field]; 
$stmt->bind_param('s', $value); 
$stmt->execute(); 
$result = $stmt->get_result(); 
unset($value); 
?> 

अधिक कोड के अलावा अन्य।

मेरा मतलब है, क्या उन्होंने इसे कार्यान्वित किया ताकि लोगों को एक प्रश्न में भेजने से पहले मूल्यों से बचना न भूलें? या यह किसी भी तरह से तेज है?

या जब मैं वही क्वेरी बार-बार उपयोग करना चाहता हूं तो मुझे इस विधि का उपयोग करना चाहिए (क्योंकि mysqli_stmt का पुन: उपयोग किया जा सकता है) और अन्य मामलों में पारंपरिक विधि का उपयोग करें?

+1

जहां तक ​​मुझे पता है कि एसक्यूएल इंजेक्शन को रोकने के लिए डिज़ाइन नहीं किया गया था, वे सिर्फ इसलिए काम करते हैं कि वे कैसे काम करते हैं। मेरी समझ से वे आपको कम ओवरहेर्ड के साथ लूप प्रश्नों की अनुमति देने के लिए डिज़ाइन किए गए हैं (केवल वेरिएबल्स निष्पादित के साथ भेजे जाते हैं, क्वेरी स्वयं ही नहीं)। हालांकि मैं गलत हो सकता हूं, और यदि मैं हूं मुझे बताया जाना चाहिए। –

+0

दूसरे उदाहरण में मुझे "कूदता है" यह है कि एसक्यूएल पाठ में कोई WHERE क्लॉज नहीं है। दूसरे कथन में स्पॉट करना आसान है, लेकिन यह पहले में अधिक छिपी हुई है। वह पहला उदाहरण है, जो 'mysqli_real_escape_string' फ़ंक्शन में लपेटा गया है, कम से कम मुझे पता है कि WHERE क्लॉज चर में नहीं है। अगर यह लपेटा नहीं गया था (w के रूप में और बहुत सारे उदाहरण देखें) मुझे नहीं पता, उस कथन को देखकर, क्या उस चर में WHERE क्लॉज शामिल था। – spencer7593

उत्तर

3

आप क्या पढ़ रहे हैं का उपयोग करना चाहिए, कि तुम mysqli_prepare() और mysqli_bind_param() कार्यों का उपयोग करने के लिए "ठीक से अपने MySQL प्रश्नों पलायन" करने की जरूरत है गलत है।

यह सच है कि अगर आप mysqli_prepare() और mysqli_bind_param() उपयोग करते हैं, आप की जरूरत नहीं है (और नहीं होना चाहिए) "पलायन" मूल्यों बाँध पैरामीटर के रूप में आपूर्ति की है। तो, उस अर्थ में, आप जो पढ़ रहे हैं उसमें कुछ सच्चाई है।

यह केवल जब असुरक्षित चर एसक्यूएल पाठ (क्वेरी की वास्तविक पाठ) है कि आप चर, "ठीक से पलायन" के लिए आम तौर पर mysqli_real_escape_string() फ़ंक्शन कॉल में चर लपेटकर द्वारा की जरूरत में शामिल किए गए हैं।

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

MySQL अब "सर्वर पक्ष" तैयार कथन का समर्थन करता है (यदि कनेक्शन में विकल्प सक्षम है), और यह एक प्रदर्शन अनुकूलन है (कुछ में मामलों) समान एसक्यूएल पाठ के दोहराए गए निष्पादन के लिए। (ओरेकल जैसे अन्य डेटाबेस में यह लंबे समय से समर्थित है, जहां तैयार बयानों का उपयोग करना हमेशा के लिए एक परिचित पैटर्न रहा है।)

प्रश्न: क्या उन्होंने [तैयार बयान] लागू किया ताकि लोग उन्हें एक प्रश्न में भेजने से पहले मूल्यों से बचना न भूलें?

एक: कोड जब तैयार बयान का उपयोग नहीं कर SQL इंजेक्शन की चपेट में के उदाहरण की संख्या, mysql_real_escape_string() समारोह के बारे में प्रलेखन के बावजूद आधार पर, आप लगता है कि निश्चित रूप से पर्याप्त कारण हो सकता है कि।

मुझे लगता है कि एक बड़ा लाभ यह है कि जब हम कोड पढ़ रहे हैं, तो हम एक एसक्यूएल कथन को सिंगल स्ट्रिंग के रूप में देख सकते हैं, चर के एक गुच्छा के संयोजन के बजाय, उद्धरण और बिंदुओं के साथ और mysql_real_escape_string पर कॉल करें, जो कि एक साधारण क्वेरी के साथ बहुत बुरा नहीं है, लेकिन एक और जटिल क्वेरी के साथ, यह सिर्फ अत्यधिक बोझिल है। ? प्लेसहोल्डर का उपयोग अधिक समझने योग्य SQL कथन के लिए बनाता है, ... सच है, मुझे यह पता लगाने के लिए कोड की अन्य पंक्तियों को देखने की आवश्यकता है कि वहां क्या मूल्य भरा हुआ है। (मुझे लगता है कि ओरेकल शैली नाम पैरामीटर :fee, :fi, :fo, :fum स्थिति ?, ?, ?, ? नोटेशन के लिए बेहतर है।) लेकिन स्टेटिक एसक्यूएल टेक्स्ट होना वास्तव में लाभ है।

प्रश्न: या यह किसी भी तरह से तेज़ है?

जैसा कि मैंने पहले उल्लेख किया था, सर्वर पक्ष तैयार किए गए बयान का उपयोग प्रदर्शन के संदर्भ में हो सकता है और लाभ हो सकता है। यह हमेशा ऐसा नहीं होता है कि यह तेज़ है, लेकिन उसी कथन के बार-बार निष्पादन के लिए, जहां केवल अंतर ही शाब्दिक मूल्य है (जैसे बार-बार आवेषण में), यह प्रदर्शन को बढ़ावा प्रदान कर सकता है।

प्रश्न: या जब मैं वही क्वेरी बार-बार उपयोग करना चाहता हूं (क्योंकि mysqli_stmt का पुन: उपयोग किया जा सकता है) और अन्य मामलों में पारंपरिक विधि का उपयोग करना है, तो क्या मैं इस विधि का उपयोग करूँ?

यह आपके ऊपर है। मेरा वरीयता स्टेटिक एसक्यूएल पाठ का उपयोग करने के लिए है। लेकिन यह वास्तव में ओरेकल का उपयोग करने के एक लंबे इतिहास से आता है, और MySQL के साथ समान पैटर्न का उपयोग स्वाभाविक रूप से फिट बैठता है। (हालांकि, डीबीआई इंटरफेस का उपयोग करते हुए पर्ल से, और जावा जेडीबीसी और माइबैटिस, या अन्य ओआरएम (हाइबरनेट, ग्लासफ़िश जेपीए, एट अल।)

उसी पैटर्न के बाद PHP में प्राकृतिक लगता है; mysqli_ और पीडीओ की शुरूआत रहस्यमय (और साथ दुर्व्यवहार) mysql_ इंटरफ़ेस से एक स्वागत योग्य राहत है।

अच्छा कोड या तो पैटर्न निम्नलिखित लिखा जा सकता है। लेकिन मैं आपको आगे सोचने के लिए, के बारे में और अधिक जटिल SQL कथन को चुनौती देने के लिए, और विकल्प का उपयोग करने के लिए कि क्या mysqli_real_escape_string() और स्थैतिक एसक्यूएल पाठ और बाध्य पैरामीटर का उपयोग करने के बजाए निष्पादित करने के लिए एक गतिशील स्ट्रिंग को एक साथ जोड़ना, पढ़ना और समझना, वास्तविक एसक्यूएल को आत्मा के लिए अधिक जटिल निष्पादित किया जा रहा है जो उन्हें ढूंढता है ves कोड बनाए रखने वे लिखा नहीं था।

मुझे लगता है कि अध्ययनों से पता चला है कि कोड लिखे जाने से दस गुना अधिक पढ़ा जाता है, यही कारण है कि हम पठनीय, समझने योग्य कोड का उत्पादन करने का प्रयास करते हैं, भले ही इसका मतलब कोड की अधिक रेखाएं हों। (जब प्रत्येक कथन एक पहचान योग्य चीज कर रहा है, तो मेरे लिए एक जटिल कथन में समेकित फ़ंक्शन कॉल की गड़बड़ी पढ़ने से मुझे समझना आसान होता है।

+0

मैंने अपने mysqli_stmt_bind_param() 'के बारे में भी सीखा, इससे पहले कि मैंने अपने SQL चर से बचने के उद्देश्य से एक और फ़ंक्शन लिखा, और मैंने पाया कि यह 'bind_param' की तुलना में अधिक परिवर्तनीय प्रकारों का समर्थन करता है (उदाहरण के लिए, यदि आप अपना स्वयं का फ़ंक्शन लिखते हैं , आप 'डेटटाइम' ऑब्जेक्ट का स्वचालित रूपांतरण 'DATETIME'-स्वरूपित स्ट्रिंग पर कर सकते हैं)। मुझे लगता है कि, अगर मैं पहले से गुणों के माध्यम से पुन: प्रयास करता हूं (उदाहरण के लिए 'foreach ($ गुण और $ संपत्ति के रूप में) {escape_fn ($ संपत्ति);} $ query = "तालिका में प्रवेश करें ($ गुण [0], $ गुण [1 ], ...); ";" मैं एक ही स्पष्टता को पूरा कर सकता हूं। परिभाषित उत्तर thx –

2

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

2

एक जोड़े को मुख्य लाभ मैंने पाया कि अच्छी तरह से लिखा गया हैं:

  1. संकलन और बयान के अनुकूलन के ऊपरी केवल एक बार खर्च किया जाता है, हालांकि बयान कई बार मार डाला जाता है। तैयार किए गए वक्तव्य संकलित किए गए समय पर सभी ऑप्टिमाइज़ेशन किए जा सकते हैं, दो कारणों से: सर्वोत्तम योजना पैरामीटर के विशिष्ट मानों पर निर्भर हो सकती है, और सर्वोत्तम योजना तालिकाओं और इंडेक्स समय के साथ बदल सकती है।
  2. तैयार किए गए कथन एसक्यूएल इंजेक्शन के खिलाफ लचीला हैं, क्योंकि पैरामीटर मान, जो बाद में एक अलग प्रोटोकॉल का उपयोग करके प्रेषित किए जाते हैं, को ठीक से बचने की आवश्यकता नहीं है। मूल बयान टेम्पलेट बाहरी इनपुट से प्राप्त नहीं है, तो एसक्यूएल इंजेक्शन घटित नहीं कर सकते हैं।

दूसरी तरफ, यदि एक क्वेरी केवल एक बार निष्पादित की जाती है, तो सर्वर-साइड तैयार कथन सर्वर के अतिरिक्त राउंड-ट्रिप की वजह से धीमा हो सकता है। कार्यान्वयन सीमाएं प्रदर्शन दंड का भी कारण बन सकती हैं: MySQL के कुछ संस्करणों ने तैयार प्रश्नों के परिणाम कैश नहीं किए हैं, और कुछ डीबीएमएस जैसे PostgreSQL निष्पादन के दौरान अतिरिक्त क्वेरी अनुकूलन नहीं करते हैं।

Source

0

मैं PHP 5.4.0 के रूप में है कि mysqli_bind_param() has been removed जोड़ना चाहते हैं।आप mysqli_stmt_bind_param()

+0

शायद इसे उत्तर से एक टिप्पणी करने के लिए बेहतर है। मुझे पता था, मैंने अभी गलत फ़ंक्शन नाम टाइप किया है, मैं हमेशा एक ओओपी दृष्टिकोण लेता हूं। –

संबंधित मुद्दे