في درس الجلسات تعلّمت كيف تُبقي المستخدم مسجّلًا للدخول. هذا الدرس يكمل الصورة: كيف تخزّن كلمة المرور نفسها في قاعدة البيانات بأمان.
لماذا لا نخزّن كلمة المرور كما هي؟
لو سُرقت قاعدة البيانات (وهذا يحدث) وكانت كلمات المرور نصًّا صريحًا، كل حساب مستخدم مكشوف فورًا — وربما حساباته الأخرى أيضًا لأن كثيرين يعيدون استخدام نفس كلمة المرور.
⚠️ لا تستخدم
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.