سؤال

أحتاج إلى الانتهاء من البرنامج النصي للمصادقة التالي.أنا ضعيف في php/pdo لذا لا أعرف كيفية السؤال عن عدد الصفوف التي تساوي صفًا واحدًا ثم تعيين معرف الجلسة من نتائج الاستعلام.لا أحتاج إلى تعيين $_SESSION['userid'] فحسب، بل أحتاج أيضًا إلى تعيين ['company'] و['security_id'] من النتائج أيضًا.

وهنا ما لدي:

$userid   = $_POST['userid'];
$password = $_POST['pass'];
if ( $userid != "" || $password != "" )
{
  $sql = "SELECT * FROM contractors WHERE userid = '" . $userid . "' AND password = '" . $password . "'";
  $result = $dbh->query( $sql );
} else
{
  echo "login failed. Your fingers are too big";
}

معلومات اختيارية:المتصفح:ثعلب النار

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

المحلول

لا تستخدم هذا الرمز أبدًا!

لديك حقنة SQL خطيرة جدًا مفتوحة هناك.كل مدخلات المستخدم التي تأخذها، سواء من ملفات تعريف الارتباط أو CGI، أو أينما, يجب تطهيرها قبل استخدامه في عبارة SQL.يمكنني بسهولة اختراق هذا النظام عن طريق محاولة تسجيل الدخول باستخدام اسم مستخدم مثل:

user'; UPDATE contractors SET password = '1337'

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

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

بقدر ما أعرف، تحتاج إلى استخدام quote وظيفة PDO لتعقيم السلسلة بشكل صحيح.(في الخلية، سيتم القيام بذلك باستخدام mysql_real_escape_string().) أنا لست خبيرًا في شركة تنمية نفط عمان، فأرجو أن يصحح شخص ما إذا كنت مخطئًا هنا.

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

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

للقيام بذلك بطريقتك، عليك أن تلاحظ أن النتيجة التي تحصل عليها من شركة تنمية نفط عمان query هو PDOStatement, ، لا يبدو أن لديها وظيفة موثوقة لحساب عدد صفوف النتائج بشكل مباشر.ما تحتاج إلى استخدامه هو fetchAll والتي تقوم بإرجاع مجموعة من الصفوف، وحساب ذلك.ومع ذلك، كما قلت، يبدو لي أن كل هذا مفتوح للفشل، لذلك أشعر بأمان أكبر عند التحقق من كلمة المرور في الكود.هناك مسافة كبيرة جدًا من التعاطف الفعلي لمطابقة كلمة المرور بالنسبة لذوقي، في مثل هذا المكان الحرج للأمان.

لذلك، للحصول على كلمة المرور الناتجة لمعرف المستخدم، يمكنك استخدام PDOStatement's fetch() الذي يقوم بإرجاع محتويات العمود من النتيجة.استخدم على سبيل المثال PDO::FETCH_ASSOC للحصول عليها في مصفوفة ترابطية بناءً على أسماء الأعمدة.

وإليك كيفية اصلاحها:

$userid_dirty   = $_POST['userid'];
$password_dirty = $_POST['pass'];
$success = false; // This is to make it more clear what the result is at the end
if ($userid != "" || $password != "") {
  $userid = $dbh->quote($userid_dirty);
  $passwordhash = hash('sha256',$password_dirty);
  $sql = "SELECT userid, passwordhash, company, security_id FROM contractors WHERE userid = ".$userid;
  $result = $dbh->query( $sql );
  if ($result) { // Check if result not empty, that userid exists
    $result_array = $result->fetch(PDO::FETCH_ASSOC);
    if ($result_array['PASSWORDHASH'] == $passwordhash) {
       // login success
       $success = true;

       // do all the login stuff here...
       // such as saving $result_array['USERID'], $result_array['COMPANY'], $result_array['SECURITY_ID'] etc. 

    } // else fail, wrong password
  } // else fail, no such user
} else {
  // fail, userid or password missing
  echo ' please enter user id and password.';
}
if (!$success) {
  echo ' login failed.';
}

بالطبع، يمكن تنظيف الكود قليلاً، ولكن هذا يجب أن يوضح ما يجب القيام به.لاحظ أنه بما أن كلمة المرور مجزأة، و لم تستخدم قط في SQL, ، فهو لا يحتاج إلى التنظيف في الواقع.لكنني تركته هناك فقط في حالة وجوده في الكود الأصلي كان المستخدمة في الاستعلام.

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

كما أنني قدمت الكود للأغراض التعليمية فقط - اعتقدت أن هذا الكود هو أوضح طريقة لشرح كيفية القيام بذلك.لذلك لا تخطئ في اعتبار هذا الموقع بمثابة خدمة لطلب الرمز.:)

نصائح أخرى

دليل فب هو مصدر ممتاز لتعلم PHP. يبدو أنك تعرف قليلا SQL، وكنت قد سمعت من شركة تنمية نفط عمان، وهي بداية جيدة. إذا كنت تبحث جوجل ل "شركة تنمية نفط عمان"، أو البحث في دليل PHP لهذا المصطلح، ستجد PDO من الدليل. يبدو أنك قد وجدت وظيفة ->query، وحتى الآن تحتاج إلى معرفة ما تقوم بإرجاع. الذهاب إلى ، ونحن نرى أنه إرجاع الكائن PDOStatement. وترتبط كلمة PDOStatement مفيد إلى صفحة ذات الصلة في هذا الدليل، الذي يسرد الأساليب المتاحة على هذا الكائن. هناك طريقة rowCount() التي من المرجح أن تفعل ما تريد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top