2010-05-16 8 views
10

मैं एक डॉक्टरेट क्वेरी कर रहा हूं और मुझे क्लॉज में वाइल्डकार्ड मैच करना है। मैं उस चर से कैसे बचूं जिसे मैं सम्मिलित करना चाहता हूं?

क्वेरी मैं प्राप्त करना चाहते हैं:

SELECT u.* FROM User as u WHERE name LIKE %var% 

php कोड अब तक:

$query = Doctrine_Query::create() 
       ->from('User u') 
       ->where(); 

जहां खंड में क्या आना चाहिए? चर मैं मैच के लिए $ नाम है

उत्तर

23

कोई भी अपने प्रश्न का सही उत्तर है, तो मैं एक बना देंगे उस पर झुकाव।

->where('u.name LIKE ?', array("%$name%")); 
->where('u.username LIKE ?', '%'.$username.'%') 

इनमें से न तो सुरक्षित हैं। मुझे कुछ परिदृश्यों की व्याख्या करने दो।

परिदृश्य 1

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

if (strlen(trim($name)) < 5) throw Boogey_Monster_Exception(); 

आपने सोचा है इस क्षेत्र को खाली छोड़ने और सभी उपयोगकर्ता नामों की सूची नीचे खींच से किसी को रोका जा सके ... लेकिन वास्तविकता में उपयोगकर्ता प्रस्तुत कर सकते हैं "_____ "या" %%%%% "या सभी उपयोगकर्ता नामों की सूची प्राप्त करने के समान कुछ भी, न केवल 5 या अधिक ज्ञात वर्णों से मेल खाता है।

मैंने व्यक्तिगत रूप से कई बड़ी, सार्वजनिक वेबसाइटों पर उपयोग किए जाने वाले हमले के इस रूप को देखा है।

परिदृश्य 2

आप और उन के बहुत सारे उपयोगकर्ता डेटा के बहुत सारे के साथ एक वेबसाइट है। आपकी उपयोगकर्ता तालिका में 10,000,000 पंक्तियां हैं। आप ज्ञात उपसर्गों को खोजकर साइट के उपयोगकर्ताओं को किसी अन्य उपयोगकर्ता का उपयोगकर्ता नाम ढूंढने में सक्षम करना चाहते हैं।

तो आप इस तरह के कुछ कोड लिखते हैं, ऊपर दिए गए उदाहरण से थोड़ा संशोधित करते हैं, केवल खोज स्ट्रिंग के बाद वाइल्डकार्ड होता है।

->where('u.name LIKE ?', array("$name%")); 

आप u.name पर एक सूचकांक है, तो इस तरह क्वेरी सूचकांक का प्रयोग करेंगे। तो यदि उपयोगकर्ता $ name = "जॉन" सबमिट करता है, तो यह क्वेरी कुशलतापूर्वक जॉन्डो, जॉनवेन, जॉनवेनेजसी आदि जैसे उपयोगकर्ताओं से मेल खाती है

हालांकि, यदि उपयोगकर्ता $ name = "% john" सबमिट करता है, तो यह क्वेरी संख्या अब इंडेक्स का उपयोग करता है और अब एक पूर्ण टेबल स्कैन की आवश्यकता है। एक बहुत बड़े डेटाबेस पर यह बहुत धीमी क्वेरी हो सकती है।

एसक्यूएलआई पर MySQL मैनुअल एक ही बात का उल्लेख करता है (पेज 78-79) और मैंने धीमी क्वेरी प्रदर्शन के कुछ उदाहरणों के लिए googled और एक लिंक पाया।

यह एक बड़ी बात की तरह नहीं लग सकता है, लेकिन साइटों एक आरडीबीएमएस द्वारा समर्थित के लिए, आरडीबीएमएस आमतौर पर एक महत्वपूर्ण टोंटी है, और प्रदर्शन इंजीनियरिंग के बहुत चारों ओर आरडीबीएमएस पर विवाद को कम करने घूमती है। यदि आपके पास कुछ ऐसे उपयोगकर्ता हैं जो 60+ सेकेंड के लिए डेटाबेस हैंडल से जुड़े हमले को लॉन्च करते हैं, और आपके पास डेटाबेस हैंडल का एक छोटा सा पूल है, तो आप देख सकते हैं कि यह आपके सभी डेटाबेस हैंडल को एकाधिकार बनाने और वैध उपयोगकर्ताओं को रोकने के लिए कैसे जल्दी से स्केल कर सकता है एक प्राप्त करने में सक्षम होने से।

लिंक

http://dev.mysql.com/tech-resources/articles/guide-to-php-security-ch3.pdf

http://forums.mysql.com/read.php?24,13397,13397

समाधान

वैसे भी, बेहतर समाधान (MySQL मैनुअल ऊपर और टिप्पणीकार @Maxence से जुड़े हुए में उल्लेख किया है के रूप में, करने के लिए है addcslashes() का उपयोग करें):

$username = addcslashes("%something_", "%_"); 

ध्यान दें कि चूंकि एसक्यूएल उदाहरण यहां तैयार कथन का उपयोग करते हैं, जो पूरी तरह से एसक्यूएल इंजेक्शन के प्रति प्रतिरोधी हैं, यह आवश्यक नहीं है या mysql_real_escape_string() का उपयोग करना वांछनीय नहीं है; यह भागने से बचने के लिए पूरी तरह से एसक्यूएल इंजेक्शन को रोकने के लिए है। जो हम रोकने की कोशिश कर रहे हैं वह वाइल्डकार्ड इंजेक्शन है, और इसके लिए एक फ़ंक्शन की आवश्यकता होती है जो दो एसक्यूएल वाइल्डकार्ड वर्णों, '%' और '_' से बच जाती है।

+1

दिलचस्प, धन्यवाद। – Tom

+1

मुझे लगता है कि डीबी पर उच्च बोझ से बचने के लिए एक अच्छा समाधान है LIKE प्रश्नों से बचने और [sphinxs] (http://sphinxsearch.com/) जैसे खोज इंजन का उपयोग करना। यह शानदार है! – JeanValjean

+0

@ mehaase मैंने देखा कि आपने दूसरे उत्तरों के लिए -1 दिया है, लेकिन आपकी विधि असुरक्षित है क्योंकि आप भागने वाले चरित्र से बचने के लिए भूल गए हैं। तो, कम से कम इसे इस तरह दिखना चाहिए: 'addcslashes ('% something_ ',' \\% _ '); '। ध्यान रखें कि MySQL में ''\\ कुछ' पसंद है '\\ कुछ'' FALSE' का मूल्यांकन करता है लेकिन '\\ कुछ' जैसा '\\\\ कुछ' 'TRUE' का मूल्यांकन करता है ;-) – Karolis

-2

कुछ बुरा इसलिए यहाँ सिद्धांत के दस्तावेज़ हुआ चाहते Google copy (जाँच जैसा भाव अनुभाग)

... 
->where('u.name LIKE ?', array("%$name%")); 
+1

क्या होता है यदि $ नाम में '%' या '\ _' जैसे विशेष वर्ण हैं? आपको addcslashes ($ name, '% \ _') – Maxence

+0

'addcslashes();' जोड़ना चाहिए? प्रश्नों के लिए किसी भी चीज़ पर स्लेश जोड़ने की कोई ज़रूरत नहीं है, चाहे आप उपयोग कर रहे हों और ओआरएम या मूल एसक्यूएल। सिद्धांत स्लेश के साथ अपने डेटा को कूड़े बिना ठीक से भागने का ख्याल रखता है। देशी mysql के लिए, 'mysql_real_escape_string ($ string) का उपयोग करें; '। दूसरों के लिए, अपने दस्तावेज़ों की जांच करें; बस 'addcslashes(); ' – adlawson

+4

@adlawson नहीं करें: सिद्धांत **' LIKE' अभिव्यक्ति के लिए '%' और '_' से बच नहीं पाएगा। इसे मैनुअल संभालना होगा। – Crozin

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