سؤال

لدي بعض التعليمات البرمجية التي تستخدم الاستعلامات ذات المعلمات لمنع الحقن، ولكنني بحاجة أيضًا إلى أن أكون قادرًا على إنشاء الاستعلام ديناميكيًا بغض النظر عن بنية الجدول.ما هي الطريقة الصحيحة للقيام بهذا العمل؟

إليك مثال، لنفترض أن لدي جدول يحتوي على أعمدة الاسم والعنوان والهاتف.لدي صفحة ويب حيث أركض إظهار الأعمدة وملء القائمة المنسدلة المحددة بها كخيارات.

بعد ذلك، لدي مربع نص يسمى يبحث.يتم استخدام مربع النص هذا كمعلمة.

حاليًا يبدو الكود الخاص بي كالتالي:

result = pquery('SELECT * FROM contacts WHERE `' + escape(column) + '`=?', search);

أشعر بشعور رديء منه بالرغم من ذلك.سبب استخدامي للاستعلامات ذات المعلمات هو تجنب الاستخدام يهرب.أيضًا، يهرب من المحتمل ألا يكون مصممًا للهروب من أسماء الأعمدة.

كيف يمكنني التأكد من أن هذا يعمل بالطريقة التي أنويها؟

يحرر:السبب وراء طلبي للاستعلامات الديناميكية هو أن المخطط قابل للتكوين من قبل المستخدم، ولن أكون موجودًا لإصلاح أي شيء تم ترميزه بشكل ثابت.

هل كانت مفيدة؟

المحلول

بدلاً من تمرير أسماء الأعمدة، ما عليك سوى تمرير المعرف الذي ستقوم بترجمته إلى اسم عمود باستخدام جدول مضمن.وهذا يعني أنك لا داعي للقلق بشأن تمرير البيانات الضارة، حيث أن جميع البيانات إما مترجمة بشكل قانوني، أو من المعروف أنها غير صالحة.الكود الزائف:

@columns = qw/Name Address Telephone/;
if ($columns[$param]) {
  $query = "select * from contacts where $columns[$param] = ?";
} else {
  die "Invalid column!";
}

run_sql($query, $search);

نصائح أخرى

الحيلة هي أن تكون واثقًا من إجراءات الهروب والتحقق من الصحة.أستخدم وظيفة الهروب SQL الخاصة بي والتي تم تحميلها بشكل زائد للأنواع المختلفة.لا يمكنني إدراج تعبيرات في أي مكان (على عكس القيم الحرفية المقتبسة) مباشرةً من إدخال المستخدم.

ومع ذلك، يمكن القيام بذلك، أوصي بوظيفة منفصلة - وصارمة - للتحقق من صحة اسم العمود.السماح لها بقبول معرف واحد فقط، شيء من هذا القبيل

/^\w[\w\d_]*$/

سيتعين عليك الاعتماد على الافتراضات التي يمكنك القيام بها بشأن أسماء الأعمدة الخاصة بك.

أستخدم ADO.NET واستخدام أوامر SQL ومعلمات SQL لتلك الأوامر التي تهتم بمشكلة الهروب.لذا، إذا كنت في بيئة أدوات Microsoft أيضًا، فيمكنني القول إنني أستخدم هذا بنجاح شديد لإنشاء SQL ديناميكي مع حماية المعلمات الخاصة بي

حظا سعيدا

قم بإنشاء العمود بناءً على نتائج استعلام آخر إلى جدول يعدد قيم المخطط المحتملة.في هذا الاستعلام الثاني، يمكنك ترميز التحديد لاسم العمود المستخدم لتعريف المخطط.إذا لم يتم إرجاع أي صفوف، فإن العمود الذي تم إدخاله غير صالح.

في لغة SQL القياسية، يمكنك تضمين المعرفات المحددة بين علامات اقتباس مزدوجة.هذا يعني ذاك:

SELECT * FROM "SomeTable" WHERE "SomeColumn" = ?

سيختار من جدول يسمى SomeTable بالأحرف الكبيرة المعروضة (وليس نسخة محولة من الاسم)، وسيطبق شرطًا على عمود يسمى SomeColumn بالأحرف الكبيرة المعروضة.

هذا في حد ذاته ليس مفيدًا جدًا، ولكن... إذا كان بإمكانك تطبيق تقنية escape() مع علامات الاقتباس المزدوجة على الأسماء التي تم إدخالها عبر نموذج الويب الخاص بك، فيمكنك إنشاء استعلامك بثقة معقولة.

بالطبع، قلت أنك تريد تجنب استخدام الهروب - وبالفعل ليس عليك استخدامه في المعلمات التي توفر فيها ؟أصحاب المكان.ولكن عندما تقوم بوضع البيانات المقدمة من المستخدم في الاستعلام، فإنك تحتاج إلى حماية نفسك من الأشخاص الضارين.

لدى أنظمة إدارة قواعد البيانات المختلفة طرق مختلفة لتوفير معرفات محددة.على سبيل المثال، يبدو أن MS SQL Server يستخدم الأقواس المربعة [SomeTable] بدلاً من علامات الاقتباس المزدوجة.

يمكن أن تحتوي أسماء الأعمدة في بعض قواعد البيانات على مسافات، مما يعني أنه سيتعين عليك اقتباس اسم العمود، ولكن إذا كانت قاعدة البيانات الخاصة بك لا تحتوي على مثل هذه الأعمدة، فما عليك سوى تشغيل اسم العمود من خلال تعبير عادي أو نوع من الفحص قبل الربط في SQL:

if ( $column !~ /^\w+$/ ) {
  die "Bad column name [$column]";
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top