מניעת מופע כפול של מחלקה
-
יש לי פרוייקט ב-PHP שבו יש מחלקה שמטפלת בבקשות API ומאפשרת גישה למסד הנתונים רק אם התקיימו אחד משני התנאים: אימות recaptcha או שקיים session פעיל (המשתמש כבר מחובר, משמע שכבר עבר אימות)
הבעיה שלי היא שבמקרה שבו האימות מתבצע דרך recaptcha אזי ברור שאני יצור מופע חדש של DB לאחר שלב האימות
אך במקרה שהמשתמש כבר מחובר זה אומר שה-class שיצר את מופע האובייקט של המשתמש כבר ניגש ל-DB ויצר כבר מופע אחד של המחלקה
מצד אחד לא הגיוני לגשת ל-DB דרךthis->user->db
, אך גם לא מסתבר ליצור מופע נפרד של DB עבור ה-user ושני עבור ה-API
מה הפתרון? -
-
@dovid כתב במניעת מופע כפול של מחלקה:
מה זה אומר מופע של DB?
חיבור למסד הנתונים
המחלקה של user צריכה להחזיר מידע על המשתמש מתוך מסד הנתונים
המחלקה של ה-API צריכה להחזיר מידע ממסד הנתונים וגם לכתוב אליו, אבל רק לאחר אימות גישה באמצעות בדיקה אם קיים session פעיל או אימות recaptcha (בצד שרת)
המחלקה של ה-API גם תרצה לבדוק את הרשאות המשתמש (משתמש, נציג, או מנהל) כדי לנהל את הגישה לפונקציות השונותאלו 2 הפונקציות שמאמתות את הגישה לפונקציה במחלקה API:
private function check_permissions( User $user, string $action ) { return isset( $this->allowed_actions_array[$action]['permissions'] ) && in_array( $this->user->role(), $this->allowed_actions_array[$action]['permissions'] ); } private function access_auth( User $user, string $action ) { if( !isset( $this->allowed_actions_array[$action]['auth'] ) ) $this->return_json( false, 'אירעה שגיאה בהגדרות הפעולה' ); $auth = $this->allowed_actions_array[$action]['auth']; switch ( $auth ) { case 'logged_in': return $user->is_logged_in(); break; case '': if( !isset( $_GET['r'] ) ) return false; else return $this->recaptcha_verification( $_GET['r'] ); break; default: return false; break; } }
הפונקציה
role
במחלקהUser
יכולה אמנם לטעון את ההרשאה מתוך ה-session (ולחסוך את הקריאה הנוספת למסד הנתונים, שתיצור מופע נוסף של החיבור ל-DB), אבל האם זה מספיק מאובטח? -
@איש-נחמד אם אני עוקב טוב אחריך במקרה שיש כבר חיבור ישנם שתי בדיקות במהלך מחזור החיים של אותה בקשה, אחת בהתחלה ממש כדי לבדוק הרשאות של משתמש והשניה כדי להביא מידע. אתה מנסה לחסוך ליצור שני מופעי גישה למסד נתונים.
אם אני צודק, אז ראשית כל @Shloimy צודק וזה כיון הפתרון, זה לא חייב להיות מבנה סינגלטון ממש, די בכך שיהיה מקום משותף לגישה לDB שנטען פעם בודדת בכל טכניקה שתבחר.
אם יוצאים נגד זה בstackoverflow נסה לצרף קישור כדי שאבין מה מדובר (אולי יש בעיה עם זה בPHP).
שנית, אל תתייגע לחסוך יצירת מופע לDB, זה לא משהו יקר כל כך להשקיע באופטימיזציה כל עוד לא ראית שהעסק מתחיל להיות מורגש.בקשר למשפט הזה:
הפונקציה role במחלקה User יכולה אמנם לטעון את ההרשאה מתוך ה-session (ולחסוך את הקריאה הנוספת למסד הנתונים, שתיצור מופע נוסף של החיבור ל-DB), אבל האם זה מספיק מאובטח?
אם כוונתך במילה session ל$_SESSION של PHP, אז אני לא רואה כל בעיית אבטחה לאחסן בו מידע (אם אתה חושב על בעיה תכתוב אולי לא נתתי על זה את הדעת), רק צריך לא לשים שמה מידי הרבה כי זה תופס פיזית מקום בדיסק, ובשעת השאילתה זה גם לוקח מקום בRAM.
-
@dovid אני מעריך את התגובה המפורטת שלך
להלן מספר קישורים ב-stackoverflow
https://stackoverflow.com/a/138012
https://stackoverflow.com/a/1020384
שם תמצא עוד קישורים למכביר -
@איש-נחמד כל הלינקים שלך מסבירים על חסרונות הסינגלטון,
אבל אף אחד מהם לא שולל את השימוש בו.
לכל דבר בעולם יש חיסרון, החסרונות המדוברים לא נוגעים למקרה שלך.
(אם אתה כן רוצה להיות מושלם תצטרך ללמוד לממש DI בPHP, אני לא יודע אפילו לתת לך לינקים, אולי זה https://medium.com/tech-tajawal/dependency-injection-di-container-in-php-a7e5d309ccc6). -
@dovid כתב במניעת מופע כפול של מחלקה:
לממש DI בPHP
בסופו של דבר העברתי את שלב אימות ה-recaptcha אל המחלקה שאחראית על יצירת ה-user, וכך אני יוצר מופע של user, בודק האם השאילתה הנוכחית מאומתת עם $_SESSION או recaptcha, ואם אחד משתי התנאים האלו נכון - יוצר מופע של db ומעביר אותו עם setter injection ל-user