لماذا المصادقة "محلية الصنع" هي قنبلة موقوتة
\n\nكل مطور PHP ثانٍ كتب نظام تسجيل دخول خاصًا به مرة واحدة على الأقل. يبدو الأمر بسيطًا: نموذج، التحقق من اسم المستخدم، جلسة. ولكن هنا، في هذه المرحلة "البسيطة"، تموت ملايين المواقع. حقن SQL، سرقة الجلسات، تخمين كلمات المرور — هجمات تحول مشروعك إلى توزيع مجاني للبيانات الشخصية.
\n\nفي هذه المقالة، سنشرح المصادقة الآمنة في PHP من الصفر. لا سحر — فقط ممارسات مثبتة تستخدمها فيسبوك، جيت هاب، وإطار العمل المفضل لديك. ستتعلم كيفية تشفير كلمات المرور بشكل صحيح، حماية الجلسات من الاختراق، وتطبيق آليات حديثة مثل JWT.
\n\nهل أنت مستعد؟ لنبدأ.
\n\n1. تشفير كلمات المرور: لماذا md5() هي حكم بالإعدام
\n\nالقاعدة الأولى للأمان: لا تقم أبدًا، أبدًا بتخزين كلمات المرور كنص عادي. القاعدة الثانية: لا تستخدم خوارزميات قديمة مثل MD5 أو SHA1. يتم حسابها في ميكروثانية، ويمكن لأي طالب لديه جهاز كمبيوتر محمول تخمين كلمة مرورك في ساعة.
\n\nفي PHP، يوجد حل مدمج — الدوال password_hash() و password_verify(). تستخدم bcrypt (أو Argon2 إذا كان PHP ≥ 7.2) وتضيف تلقائيًا "ملحًا" — سلسلة عشوائية تجعل كل تجزئة فريدة.
مثال على التشفير الصحيح
\n// تسجيل مستخدم جديد\n$password = $_POST['password'];\n$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);\n\n// احفظ $hash في قاعدة البيانات\n// لا حاجة لإضافة الملح يدويًا! PHP يفعل كل شيء بنفسه.\n\n\nالتحقق من كلمة المرور عند تسجيل الدخول
\n// تسجيل دخول المستخدم\n$inputPassword = $_POST['password'];\n$storedHash = 'من قاعدة البيانات';\n\nif (password_verify($inputPassword, $storedHash)) {\n // كلمة المرور صحيحة — اسمح بالدخول\n} else {\n // كلمة المرور خاطئة\n}\n\n\nلاحظ المعامل cost. يحدد "تكلفة" حساب التجزئة. كلما زاد الرقم، زاد الوقت الذي يستغرقه المهاجم لتخمين كلمة المرور. لعام 2024، cost = 12 هو الوسط الذهبي بين الأمان والسرعة.
2. الجلسات: كيف لا تسلم مفاتيح المنزل
\n\nبعد تسجيل الدخول الناجح، نبدأ عادةً جلسة. لكن جلسات PHP القياسية بها نقاط ضعف: معرفات يمكن توقعها، تسرب عبر URL، تثبيت الجلسة (session fixation).
\n\nإعداد الجلسة بشكل آمن
\n// في بداية السكريبت، قبل إخراج أي HTML\nini_set('session.use_only_cookies', 1);\nini_set('session.use_strict_mode', 1);\nini_set('session.cookie_httponly', 1);\nini_set('session.cookie_secure', 1); // فقط لـ HTTPS\nini_set('session.cookie_samesite', 'Lax');\n\nsession_start();\n\n// أعد توليد معرف الجلسة بعد تسجيل الدخول\nif ($login_success) {\n session_regenerate_id(true);\n $_SESSION['user_id'] = $user['id'];\n}\n\n\nماذا فعلنا:
\n- \n
- use_only_cookies — نمنع تمرير معرف الجلسة عبر URL (حتى لا يُسرق من الرابط) \n
- use_strict_mode — نحظر الجلسات غير المهيأة \n
- httponly — نمنع وصول JavaScript إلى كعكة الجلسة (حماية من XSS) \n
- secure — تُرسل الكعكة فقط عبر HTTPS \n
- samesite — حماية من هجمات CSRF عبر تزوير الطلبات عبر المواقع \n
والأهم: أعد دائمًا توليد معرف الجلسة بعد تسجيل الدخول. وإلا، يمكن للمهاجم أن يقدم للمستخدم معرف جلسة خاصًا به مسبقًا ويختطف الحساب.
\n\n3. الحماية من CSRF: التحقق من أن الطلب مرسل منك
\n\nCSRF (Cross-Site Request Forgery) — هجوم عندما ينتقل المستخدم إلى رابط مثل /delete-account?id=1 ويقوم، دون قصد، بتنفيذ إجراء. لتجنب ذلك، استخدم الرموز المميزة (tokens).
توليد والتحقق من رمز CSRF
\n// توليد الرمز (في بداية الجلسة أو عند تحميل النموذج)\nif (empty(