התחברות לפאנל הניהול מורכבת מסיסמה (bcrypt), מאימות דו-שלבי אופציונלי (WIZZO ID או קוד במייל/SMS) וסשן מבוסס טוקן שנשמר בטבלה. בדף הזה מוסבר מה קורה בכל שלב, מה נשמר איפה, ואיך מנהל מפתח נכנס בשם מנהל אחר. כל הפונקציות הן מתודות סטטיות של המחלקה ADMIN (system/collections/ADMIN.php) והקונטרולר system/admin_login.
{admin} בדף הוא CONFIG::$admin_url, ו-system/ הוא תיקיית הליבה (api/core בריפו).
זרימת ההתחברות#
כשמבקר שאינו מחובר נכנס לכתובת {admin}, PAGE::load בוחר את ה-theme admin_login במקום admin_panel. הטופס שולח POST אל system/admin_login?action=login.
- בדיקת מקור: הקונטרולר בודק שה-host של ה-
Refererתואם לאתר. - CSRF (double submit): הטופס נושא טוקן שמקורו בעוגייה
admin_csrf.ADMIN::generate_csrf_cookie()יוצרת אותה (32 בתים אקראיים בהקסדצימלי, תוקף שעה) או מחזירה את הקיימת, ו-ADMIN::verify_csrf_token($posted)משווה עםhash_equalsומחזירהfalseאם אחד הערכים ריק. - בדיקת פרטים:
ADMIN::check_details($username, $password, $phone = false, $record_bad_attempt = true)מאמתת את הסיסמה מול ה-hash (bcrypt). - אימות שני: לפי הגדרות המנהל (ראו להלן).
- יצירת סשן:
ADMIN::admin_log(...)יוצרת שורה ב-CRM_adminPanel_sessionsומציבה עוגיות.
נעילה אחרי ניסיונות כושלים#
check_details סופרת ניסיונות כושלים מהטבלה adminPanel_admins_bad_attempts. אחרי 5 ניסיונות לכל משתמש ב-10 דקות, או 15 לכל כתובת IP, היא מחזירה "to_many_ettempts" (כך מאויית הערך בקוד) ולא בודקת את הסיסמה. למנהל אפשר להגדיר גם רשימת allow_ip (שדה מוצפן ב-MISC::encode); כניסה מכתובת שלא ברשימה נדחית.
הרשימה allow_ip נערכת בטופס המנהל בשדה Tags. מנהל ללא רשימה יכול להתחבר מכל כתובת.
אימות דו-שלבי#
הגדרת המנהל (CRM_adminPanel_admins) קובעת מה קורה אחרי סיסמה נכונה:
| מצב | התנהגות |
|---|---|
skip_otp = 1 | כניסה מיידית, בלי שלב שני |
| WIZZO ID זמין | wizzo_auth::send שולחת בקשה ל-https://auth.wizzo.co.il/api/send_otp ומקבלת טוקן. הטוקן חוזר לדפדפן בכותרות otp_token ו-otp_push, והדפדפן ממתין לאישור בטלפון של המנהל |
| WIZZO ID לא זמין | קוד בן 4 ספרות נשלח במייל (או ב-SMS דרך המודל m_sms). ה-hash של הקוד נשמר ב-phone_last_code ותאריך השליחה ב-phone_last_code_date; שליחה חוזרת אפשרית רק אחרי 3 דקות |
ההמתנה לאישור WIZZO ID היא long-poll: כל קריאה ל-check_otp ממתינה עד 25 שניות מול השרת, וכל בקשה בדפדפן עד כ-50 שניות. התשובה היא true (אושר), declined (נדחה) או false (עדיין ממתין). באישור, הטוקן של המפתח (developer_token) נשמר במנהל ונקראת admin_log. את הקוד שנשלח במייל או ב-SMS מאמתים ב-system/admin_login?action=phone.
סשנים: הטבלה adminPanel_sessions#
כל התחברות מוצלחת יוצרת שורה בטבלה CRM_adminPanel_sessions. הטבלה נוצרת אוטומטית (ensure_sessions_table()) אם היא חסרה.
| עמודה | משמעות |
|---|---|
id | מפתח |
admin_id | המנהל |
token | bin2hex(random_bytes(32)), הערך שבעוגייה |
ip, user_agent, device_label | פרטי המכשיר, להצגה במסך "ההתחברויות שלי" |
created_at, last_active_at, expires_at | מחזור החיים |
is_impersonated, impersonated_by | סשן של "התחבר כמנהל" (ראו להלן) |
עוגיות#
| עוגייה | תפקיד |
|---|---|
admin_session | הטוקן. נקבעת עם COOKIES::set_secure, 168 שעות (שבוע), HttpOnly, Secure, SameSite=Lax |
admin_logged | דגל שה-JavaScript יכול לקרוא (בלי הטוקן עצמו) |
admin_csrf | טוקן ה-CSRF (double submit) של טופס ההתחברות; פאנלים כמו file_manager משתמשים בו גם לפעולות כתיבה שלהם |
בכל בקשה ADMIN::get_id() מאתרת את הסשן לפי העוגייה. היא מאריכה את expires_at ו-last_active_at לכל היותר פעם ב-5 דקות, כדי לא לכתוב לבסיס הנתונים בכל בקשה. עוגיית admin_token ישנה (מהמנגנון הקודם) מועברת אוטומטית לסשן חדש.
פונקציות ניהול סשנים#
| פונקציה | מה עושה |
|---|---|
ADMIN::admin_logout() | מוחקת את שורת הסשן ואת העוגיות. נקראת גם דרך GET system/admin_login/logout |
ADMIN::logout_all() | מנתקת את כל הסשנים של המנהל |
ADMIN::get_active_sessions() | רשימת הסשנים הפעילים של המנהל הנוכחי |
ADMIN::get_current_session_id() | מזהה הסשן הנוכחי |
ADMIN::revoke_session($id) | מבטלת סשן אחד |
ADMIN::invalidate_sessions_on_password_change(...) | מבטלת סשנים אחרי החלפת סיסמה |
ADMIN::cleanup_expired_sessions() | מוחקת סשנים שפג תוקפם |
ניקוי הסשנים שפג תוקפם רץ מדי יום ב-03:00 דרך הקונטרולר admin_session_cleanup/run (cron 0 3 * * *).
בפאנל Admins שלושה עמודי POST מנהליים: my_sessions, revoke_session ו-logout_all_sessions. השניים האחרונים מקבלים session_id ב-POST ומחזירים ok.
logout ו-ניקוי המטמון (clear_cache) מתבצעים גם ב-GET, ולכן קישור או תמונה בדף זר יכולים להפעיל אותם. אל תוסיפו פעולות משנות מצב על GET בפאנלים שלכם.התחברות כמנהל אחר (login_as)#
מפתח שמתחבר עם WIZZO ID יכול להיכנס בשם מנהל אחר כדי לשחזר בעיה. הכפתור "התחבר כמנהל" ברשימת Admins מוצג רק כש-ADMIN::is_developer() נכון, ולא עבור המשתמש עצמו.
ADMIN::create_login_as_token(...)מייצרת מטען (target_id,requester_id, זמן וערך אקראי) מוצפן ב-MISC::encode.- הקישור הוא
{site_url}/system/admin_login/login_as?token=.... validate_login_as_tokenמקבלת טוקן בן 60 שניות לכל היותר.- הקונטרולר דורש שלמבקש יהיה
developer_tokenלא ריק. ADMIN::admin_log_impersonate(...)יוצרת סשן עםis_impersonated = 1,impersonated_byשמצביע על המפתח, ו-device_labelשמסתיים ב-(impersonated).
כל סשן "כמנהל" נשמר בטבלה עם מי שביצע אותו, ולכן אפשר לשאול בכל רגע מי נכנס בשם מי: SELECT admin_id, impersonated_by, created_at FROM CRM_adminPanel_sessions WHERE is_impersonated = 1.
מפתחים וטוקן המפתח#
ADMIN::is_developer() נקבעת פעם אחת בכל בקשה. היא קוראת את developer_token של המנהל ומאמתת אותו ב-decode_developer_token: חתימת RSA-SHA256 על ההודעה dev|user_id|time מול המפתח הציבורי של WIZZO ID (קבוע ב-ADMIN.php). בלי openssl האימות נכשל (fail closed), כלומר אף אחד לא נחשב מפתח.
טוקן שפג תוקפו מחודש ב-wizzo_auth::renew_developer_token (קריאה ל-auth.wizzo.co.il/api/renew_developer_token, timeout של 10 שניות). אם השרת דוחה את החידוש, הטוקן נמחק; אם אין תשובה (תקלת רשת), הטוקן נשמר.
מי נחשב מפתח משפיע על: פאנלים שסומנו perm_developer, הכפתור login_as, וסוגי פאנלים כמו composer ו-file_manager (ראו הרשאות).
המפתח הציבורי של WIZZO ID הוא קבוע בקוד הליבה ואסור לשנות אותו באתר: הוא מה שמבדיל בין מפתח אמיתי למי שמזייף טוקן. ההצפנה של MISC::encode (המשמשת את טוקן login_as ואת רשימת ה-IP) מתבססת על מפתח ברירת מחדל שחייבים להחליף לכל אתר עם MISC::set_encrypt_secret_keys (ראו הקשחה).
ראו גם#
- הרשאות: מה מנהל מחובר רשאי לעשות
- סקירת הפאנל: איך בקשה לפאנל מגיעה למחלקה
- עוגיות וסשן: עוגיות האתר הציבורי
- מודל האבטחה
- רפרנס עוגיות, סשן והתחברות