diff --git a/Admin/auth/login.php b/Admin/auth/login.php index b31767b..4f0a390 100755 --- a/Admin/auth/login.php +++ b/Admin/auth/login.php @@ -42,29 +42,39 @@ try { // 3. توليد رمز تحقق OTP وإرساله عبر WhatsApp $otp = rand(10000, 99999); - $phone = $admin['phone'] ?? ''; // تأكد من وجود حقل الهاتف في الجدول + $encryptedPhone = $admin['phone'] ?? ''; - if (empty($phone)) { - // Fallback للأرقام المسموح لها إذا لم يكن الرقم مسجلاً في الجدول - // (قد نحتاج لتحسين هذه النقطة لاحقاً) + if (empty($encryptedPhone)) { jsonError("رقم الهاتف غير مسجل لهذا الحساب. يرجى مراجعة الإدارة."); exit; } + // فك تشفير رقم الهاتف (مخزن مشفراً في قاعدة البيانات) + $phone = $encryptionHelper->decryptData($encryptedPhone); + if (!$phone || empty($phone)) { + // إذا فشل فك التشفير، قد يكون الرقم مخزناً بدون تشفير + $phone = $encryptedPhone; + } + $messageBody = "رمز التحقق الخاص بك للدخول إلى لوحة الإدارة هو: $otp"; $success = sendWhatsAppFromServer($phone, $messageBody); if ($success) { - // حفظ الرمز في قاعدة البيانات للتحقق لاحقاً + // حفظ الرمز مشفراً في قاعدة البيانات (وحفظ رقم الهاتف مشفراً أيضاً) + $encryptedOtp = $encryptionHelper->encryptData((string)$otp); + $stmt = $con->prepare("INSERT INTO token_verification_admin (phone_number, token, expiration_time) VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 10 MINUTE)) ON DUPLICATE KEY UPDATE token = VALUES(token), expiration_time = VALUES(expiration_time)"); - $stmt->execute([$phone, $otp]); + $stmt->execute([$encryptedPhone, $encryptedOtp]); + + // إخفاء جزء من الرقم في الاستجابة للأمان + $maskedPhone = substr($phone, 0, 4) . '****' . substr($phone, -3); printSuccess([ "status" => "otp_required", "message" => "تم إرسال رمز التحقق إلى WhatsApp الخاص بك.", - "phone" => $phone + "phone" => $maskedPhone ]); } else { jsonError("فشل في إرسال رمز التحقق عبر WhatsApp."); diff --git a/Admin/auth/verify_login.php b/Admin/auth/verify_login.php index ecc4524..0a11157 100644 --- a/Admin/auth/verify_login.php +++ b/Admin/auth/verify_login.php @@ -4,53 +4,53 @@ * الخطوة الثانية من تسجيل الدخول: التحقق من الـ OTP وإصدار التوكن النهائي */ require_once __DIR__ . '/../../core/bootstrap.php'; +require_once __DIR__ . '/../../functions.php'; -$phone = filterRequest('phone'); $otp = filterRequest('otp'); $fingerprint = filterRequest('fingerprint'); // مطلوب لربط التوكن بالجهاز $audience = filterRequest('aud') ?? 'admin'; -if (empty($phone) || empty($otp) || empty($fingerprint)) { - jsonError("Phone, OTP and fingerprint are required."); +if (empty($otp) || empty($fingerprint)) { + jsonError("OTP and fingerprint are required."); exit; } try { $con = Database::get('main'); - // 1. التحقق من الـ OTP + // 1. جلب بيانات المسؤول عبر البصمة (مصدر موثوق وغير مشفر) + $fpHash = hash('sha256', $fingerprint); + $stmt = $con->prepare("SELECT * FROM adminUser WHERE fingerprint_hash = :fp LIMIT 1"); + $stmt->execute([':fp' => $fpHash]); + $admin = $stmt->fetch(PDO::FETCH_ASSOC); + + if (!$admin) { + jsonError("المسؤول غير موجود أو البصمة غير مطابقة."); + exit; + } + + // 2. رقم الهاتف المشفر (للاستخدام في جدول OTP) + $encryptedPhone = $admin['phone'] ?? ''; + + // فك تشفيره لو احتجنا إرساله أو عرضه، لكن هنا نحن نحتاج المشفر للبحث + // $phone = $encryptionHelper->decryptData($encryptedPhone); + + // تشفير الرمز (OTP) القادم من التطبيق للمقارنة + $encryptedOtp = $encryptionHelper->encryptData((string)$otp); + + // 3. التحقق من الـ OTP (باستخدام القيم المشفرة) $stmt = $con->prepare("SELECT * FROM token_verification_admin WHERE phone_number = ? AND token = ? AND expiration_time >= NOW()"); -$stmt->execute([$phone, $otp]); + $stmt->execute([$encryptedPhone, $encryptedOtp]); if ($stmt->rowCount() === 0) { jsonError("رمز التحقق غير صالح أو منتهي الصلاحية."); exit; } - // حذف الرمز بعد استخدامه لمرة واحدة - $con->prepare("DELETE FROM token_verification_admin WHERE phone_number = ?")->execute([$phone]); - - // 2. جلب بيانات المسؤول - $stmt = $con->prepare("SELECT * FROM adminUser WHERE phone = ? LIMIT 1"); - $stmt->execute([$phone]); - $admin = $stmt->fetch(PDO::FETCH_ASSOC); - - if (!$admin) { - jsonError("المسؤول غير موجود."); - exit; - } - - // 3. التحقق من البصمة (اختياري لكن مفضل لزيادة الأمان) - $fpHash = hash('sha256', $fingerprint); - if ($admin['fingerprint_hash'] !== $fpHash) { - // إذا كانت البصمة مختلفة، ربما يحاول تسجيل الدخول من جهاز آخر - // يمكننا إما المنع أو السماح وتحديث البصمة (حسب السياسة) - // هنا سنقوم بالمنع لزيادة الأمان - jsonError("عذراً، لا يمكن تسجيل الدخول من هذا الجهاز."); - exit; - } + // حذف الرمز بعد استخدامه لمرة واحدة (باستخدام الرقم المشفر) + $con->prepare("DELETE FROM token_verification_admin WHERE phone_number = ?")->execute([$encryptedPhone]); // 4. إصدار التوكن النهائي $jwtService = new JwtService($redis); @@ -66,7 +66,7 @@ $stmt->execute([$phone, $otp]); $jwt = $jwtService->generateAccessToken($admin['id'], $role, $audience, $fingerprint); - // فك تشفير الاسم للعرض + // فك تشفير البيانات للعرض $admin['name'] = $encryptionHelper->decryptData($admin['name']) ?: $admin['name']; unset($admin['password']);