تخطَّ إلى المحتوى

🐘 شرح PHP

تجزئة كلمات المرور والأمان

الدرس 28 من 29· ⏱ 2 دقائق قراءة· 🗓 آخر تحديث: ٢١ يوليو ٢٠٢٦

في درس الجلسات تعلّمت كيف تُبقي المستخدم مسجّلًا للدخول. هذا الدرس يكمل الصورة: كيف تخزّن كلمة المرور نفسها في قاعدة البيانات بأمان.

لماذا لا نخزّن كلمة المرور كما هي؟

لو سُرقت قاعدة البيانات (وهذا يحدث) وكانت كلمات المرور نصًّا صريحًا، كل حساب مستخدم مكشوف فورًا — وربما حساباته الأخرى أيضًا لأن كثيرين يعيدون استخدام نفس كلمة المرور.

⚠️ لا تستخدم md5() أو sha1() لكلمات المرور أبدًا. صُمّمتا للسرعة لا للأمان، وهذا بالضبط ما يجعلها سهلة الكسر بالقوة العمياء. استخدم دائمًا password_hash().

password_hash: تجزئة كلمة المرور

تُنتج نصًّا مُجزَّأً (hash) يحتوي الخوارزمية وملح عشوائي (salt) والنتيجة معًا — لا تحتاج تخزين الملح بشكل منفصل:

<?php
$password = $_POST["password"];   // من نموذج التسجيل

$hash = password_hash($password, PASSWORD_DEFAULT);

// $hash شيء يشبه:
// $2y$12$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi.
// خزّنه في عمود VARCHAR(255) في جدول المستخدمين
?>

PASSWORD_DEFAULT يستخدم أقوى خوارزمية مدعومة حاليًا (bcrypt وقت كتابة هذا الدرس)، وقد تتغيّر مستقبلًا تلقائيًا مع تحديثات PHP — لذلك اجعل عمود التخزين واسعًا بما يكفي (255 حرفًا مقترح).

password_verify: التحقّق عند تسجيل الدخول

قارن كلمة المرور المُدخَلة بالـ hash المخزَّن — دون فك تشفيره (فهو اتجاه واحد أصلًا):

<?php
$enteredPassword = $_POST["password"];
$storedHash = $user["password_hash"];   // من قاعدة البيانات

if (password_verify($enteredPassword, $storedHash)) {
    echo "تسجيل الدخول ناجح";
    // $_SESSION["user_id"] = $user["id"];
} else {
    echo "كلمة المرور غير صحيحة";
}
?>

مثال متكامل: تسجيل ثم دخول

<?php
// عند التسجيل
$hash = password_hash($_POST["password"], PASSWORD_DEFAULT);
$stmt = $pdo->prepare(
    "INSERT INTO users (email, password_hash) VALUES (?, ?)"
);
$stmt->execute([$_POST["email"], $hash]);

// عند تسجيل الدخول
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$_POST["email"]]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);

if ($user && password_verify($_POST["password"], $user["password_hash"])) {
    session_start();
    $_SESSION["user_id"] = $user["id"];
} else {
    echo "بيانات الدخول غير صحيحة";
}
?>

💡 اجعل رسالة الخطأ عامة ("بيانات الدخول غير صحيحة") سواء كان البريد غير موجود أو كلمة المرور خاطئة — تحديد أيّهما يسهّل على المهاجم تخمين الحسابات الموجودة.

أخطاء شائعة

  • استخدام md5()/sha1() أو تشفير عكوس (encryption) بدل تجزئة مخصّصة لكلمات المرور.
  • محاولة "فك تشفير" الـ hash — غير ممكن أصلًا، دائمًا قارن بـ password_verify().
  • تخزين كلمة المرور الأصلية في السجلّات (logs) أو رسائل البريد عند التسجيل.
  • عمود تخزين ضيّق (مثل CHAR(32) المتبقّي من عادة md5) لا يتّسع لطول hash الحديث.

🎯 التالي: الخلاصة وما بعد PHP.

شرح تجزئة كلمات المرور والأمان — PHP بالعربي
تجزئة كلمات المرور والأمانPHP بالعربي · The Code Fix

📚 لمزيد من التعمّق في PHP، راجِع التوثيق الرسمي لـ PHP.

هل كان هذا الدرس مفيدًا؟