2015-10-15 17 views
7

मेरे पास Project तालिका है जिसमें दो कॉलम हैं - ProjectId और ProjectName - और एक ऐसा फ़ंक्शन लिख रहा हूं जो किसी दिए गए नाम के साथ किसी प्रोजेक्ट के आईडी के लिए डेटाबेस क्वेरी करने के लिए SqlCommand बनाता है और निष्पादित करता है। यह आदेश काम करता है, लेकिन SQL Injection के लिए असुरक्षित है:String.Format क्यों काम करता है लेकिन SqlCommand.Parameters.क्या नहीं?

string sqlCommand = String.Format("SELECT {0} FROM {1} WHERE {2} = {3}", 
      attributeParam, tableParam, idParam, surroundWithSingleQuotes(idValue)); 

SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection); 
using (SqlDataAdapter adapter = new SqlDataAdapter(command)) 
{ 
    DataTable attributes = new DataTable(); 
    adapter.Fill(attributes); 
    ... 
} 

attributeParam, tableParam, idParam, और idValue सभी स्ट्रिंग्स हैं। उदाहरण के लिए, वे "ProjectId", "Project", "ProjectName", और "MyFirstProject" क्रमशः हो सकते हैं। surroundWithSingleQuotes'' के साथ एक स्ट्रिंग को घेरता है, इसलिए surroundWithSingleQuotes(idValue) == "'MyFirstProject'"। मैं इस कार्य को यथासंभव सामान्य रूप से लिखने की कोशिश कर रहा हूं क्योंकि मैं भविष्य में किसी तालिका से दी गई सभी विशेषता प्राप्त करना चाहता हूं।

हालांकि उपरोक्त String.Format काम करता है, यह नहीं करता है:

string sqlCommand = String.Format("SELECT @attributeparam FROM {0} WHERE " + 
    "@idparam = @idvalue", tableParam); 

command.Parameters.Add(new SqlParameter("@attributeparam", attributeParam)); 
command.Parameters.Add(new SqlParameter("@idparam", idParam)); 
command.Parameters.Add(new SqlParameter("@idvalue", 
    surroundWithSingleQuotes(idValue))); 

SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection); 
using (SqlDataAdapter adapter = new SqlDataAdapter(command)) 
{ 
    DataTable attributes = new DataTable(); 
    adapter.Fill(attributes); 
    ... 
} 

मुझे यकीन है कि क्यों नहीं कर रहा हूँ। मुझे कोई त्रुटि संदेश नहीं मिलता है, लेकिन जब मैं को SqlDataAdapter का उपयोग करके भरता हूं, तो डेटाटेबल में कुछ भी नहीं है।

  • this answer और Microsoft's documentation के बाद, AddWithValue का उपयोग कर या Parameters.Add और SqlParameter.Value का उपयोग कर: यहाँ विभिन्न दृष्टिकोण मैं लिया है, कोई लाभ नहीं हुआ है।
  • चुनिंदा या तो वास्तविक मूल्य या पैरामीटर तार के साथ String.Format में {0}, {1}, {2}, और {3} की जगह।

मेरे कोड में अन्य स्थानों में, मैंने पैरामीट्रिज्ड प्रश्नों का उपयोग किया है (हालांकि केवल एक पैरामीटर के साथ) कोई समस्या नहीं है।

+2

एकमात्र टुकड़ा पैरामीटर सीधे प्रतिस्थापित कर सकते हैं '{3}' है। –

+2

आप कॉलम के नाम के लिए पैरामीटर का उपयोग नहीं कर सकते हैं। इसके लिए आपको अभी भी 'string.Format' का उपयोग करना होगा, बस तालिका के नाम की तरह। – juharr

उत्तर

7

एसक्यूएल में मूल रूप से पैरामीटर केवल मान के लिए काम करते हैं - कॉलम या तालिकाओं की पहचानकर्ता नहीं। आपके उदाहरण में, केवल अंतिम पैरामीटर एक मान का प्रतिनिधित्व करता है।

यदि आपको अपने कॉलम और टेबल नामों के संदर्भ में गतिशील होने की आवश्यकता है, तो आपको स्वयं SQL के उस भाग को बनाना होगा। एसक्यूएल इंजेक्शन हमलों से जुड़े सभी सामान्य कारणों के लिए बहुत सावधान रहें। आदर्श रूप से, केवल तालिका और कॉलम मानों के ज्ञात श्वेतसूची की अनुमति दें। यदि आपको अधिक सामान्य होने की आवश्यकता है, तो मैं कीवर्ड के साथ संघर्ष से बचने के लिए बहुत ही सीमित सत्यापन और quote the identifiers निष्पादित करने का सुझाव दूंगा (या पूरी तरह से, आदर्श रूप से उन पर रोक लगाऊंगा)।

निश्चित रूप से मूल्यों के लिए SQL पैरामीटर का उपयोग करते रहें।

+0

बेहद सहायक - बहुत बहुत धन्यवाद! – rln

0

यह एक वैध कथन है: SELECT * FROM SomeTable WHERE [email protected]

इस जबकि नहीं है: SELECT * FROM @param

इसका मतलब यह है कि आप और मूल्यों के लिए पैरामीटर का उपयोग नहीं कर सकते हैं तालिका के नाम, देखने नाम, स्तंभ नाम आदि

के लिए
संबंधित मुद्दे