אימות משתמשים וממשק ניהול בנוד
-
עבור ממשק ניהול שאני בונה ללקוחות. (עד כה השתמשתי בפריימוורק PHP בשם YII2, וכעת אני רוצה משהו מתחילה עד הסוף לבד, בצורה של html+js סטטי קבוע, וכל הפעולות מבוצעות על ידי API שהוא בשרת ב nodejs).
לכל משתמש יש שם משתמש וסיסמא.
מנהל יכול לנהל מספר מוסדות שרשומים בחשבונו.
משתמש רגיל יוכל לנהל רק את המוסד עליו הוא אחראי.
ישנם רמת הרשאות לכל משתמש מה הוא יכול לעשות.אשמח לכיון מה הדרך הנכונה לפתח זאת.
דהיינו:
א. איך לבצע את האימות?
אני חושב שהכיון אמור להיות, פונקציית הזדהות המקבל משתמש וסיסמא, וRememberMe, ויוצר עוגיה או כל היכר אחר המועבר ללקוח, ובכל שאר הקריאות הזיהוי מבוצע על ידי העוגיה.
יותר מזאת, חשבתי לעשות טבלת סשנים עם עמודות: מזהה A_I, מזהה משתמש, טוקן הנוצר בצורה רנדומאלית וייחודית (חשבתי על זה), תאריך תפוגה, תאריך יצירה, תאריך שימוש אחרון. משהו כזה, ובכל התחברות מחדש אני יוצר טוקן, מוסיף לטבלה, ומחזיר ללקוח את הID של הטוקן + הטוקן, שיישמר בעוגיה.
בכל שאר הפונקציות קריאה ועריכה וכו' אני בודק האם קיים עוגייה, האם הID והטוקן קיימים (בשורה אחת) וברי תוקף, ולפי זה מבצע את הפעולה.
ופונקציית LogOut מוחקת או מאפסת את התוקף של הטוקן.
רק שבזה אני מתלבט האם עלי לעשות איזה הצפנה כל שהיא לקריאה ויצירת העוגיה, האם ניתן לשלוח ללקוח ישירות את הטוקן והID כמות שהם, כי הם לא משקפים כלום, או שיש לחשוש שניתן לפענח את הרצף של הID והטוקן וכו', וא"כ יש להצפין כמה שיותר..לאחר שאימתתי כבר את המשתמש
ב. איך לנהל את ההרשאות?- יש לבדוק שיש לו הרשאת גישה למוסד זה.
- לבדוק שיש לו הרשאת גישה לטבלה/פונקציה זו (קריאה או עריכה).
פחות או יותר רמות ההרשאה תהיינה שוות, משתמש רגיל יש לו הרשאות קריאה ל(מוסד בודד) כמה טבלאות לקריאה ועריכה, ולאחרים רק קריאה, ולאחרים ללא גישה כלל.
משתמש מנהל יוכל לגשת לעריכה של יותר נתונים
משתמש ראשי (אני או עובד שלי) יוכל לגשת לעוד יותר נתונים
א"כ איך והיכן עלי לשמור את רמות ההרשאות?
ליצור טבלת הרשאות שאני יכניס שם שמות של פונקציות/איזורים/שמות של טבלאות (??), ולכל משתמש לשמור בעמודה את רמת ההרשאה?
ג. איך לשמור את הסיסמא אצלי? לכאורה היא צריכה להיות מוצפנת, אלא א"כ אני יצרתי אותה ושלחתי למשתמש סיסמא מוכנה (כך זה בדר"כ), וא"כ האם יש בעיה לשמור את הסיסמא גלוי? (כמובן שזה יותר קל לתחזק ולשחזר ולאמת) אחרת, באיזה סוג הצפנה להצפין בעת היצירה, ואיך בודקים להשוות בעת התחברות של לקוח?
יישר כח
-
@חוקר העולם של הזדהות והשראות הוא ותיק ובנוי מאוד. מאוד מומלץ לא לעשות כלום, כי כל דבר שתעשה זה המצאת גלגל על כל החסרונות שיש בזה.
בא נחלק את מה שכתבת:א. שמות וסיסמאות.
במקרה שלך אתה יצר גם משתמש וגם סיסמה, אוקי.
אבל מכיוון שאולי תיתן למשתמש לבחור סיסמה, ומכיוון שסיסמת משתמש נחשבת משהו אישי מאוד, מקובל לא לשמור סיסמאות בכלל. פשוט שומרים תוצאה חד סטרית של הסיסמה, מה שנקרא גיבוב שלה. אז אנחנו צריכים טבלה של משתמשים, עמודה של ערך מגובב ובהינתן שם וסיסמה, מפעילים את פונקציית הגיבוב על הסיסמה, ובודקים עם יש שם+גיבוב מתאימים. הנה דוגמת גיבוב.ב. שסנים (עונות = היכר לייחודיתו של משתמש על פני בקשות שונות)
כדי לדעת שהמשתמש כבר נתן שם וסיסמה נכונים הצעת להשתמש בעוגיות או כל היכר אחר המועבד ללקוח. יפה מאוד, זה אכן הדרך. ליתר דיוק, העוגיות.
בניהול של שסן העלית נקודות נכונות: יש בעיה שלקוח "ינחש" שסנים אחרים. לכן העוגיה חייבת להיות קשקוש ולא מס' רץ (uuid רנדומלי זה אכן נחמד), וכזה קשקוש שבלתי סביר לניחוש בפרק הזמן בה היא בתוקף. ובגלל כל הסלט הזה של: קביעת עוגיה, קביעת תוקף, ניהול טבלת העוגיות ועוד היבטי אבטחה, משתמשים בספריה שעושה את כל זה לגמרי אוטומטית express-session. הספריה הזו ממש שקופה, אתה מחליט על בקשה מסויימת שהמשתמש הזה הוא בלתי נחמד, אז אתה מסמן את req.session.user_dafuk = true, או אם העדפה שלו היא מיון לפי עיר req.session.filterBy = 'city' ואח"כ בכל בקשה אתה פונה למשתנה הזה, ולמרבה הפלא הוא מכיל את המידע שהוצב בבקשות הקודמות, זה כיף!ג. הרשאות
באקספרס יש מושג של middelware וזה אומר שאתה יכול לעבד בקשה (וגם את התשובה החוזרת) בכמה "שכבות", אתה יכול לעשות שכל הבקשות יעברו דרך פוקנציה שבודקת אם המשתמש מחובר ועושה חישובים שונים וכדומה.
אפשר בצורה הזו בקלות להגביל גישה של משתמש/סוג משתמש על הרבה פונקציות בלי לעשות if בכל קוד וקוד (שדרך זו מאוד מקשה על התחזוקה, ומעלה מאוד את הסיכויים לפשלות אבטחה בגלל ריבוי קוד וריבוי נקודות בדיקה).
בנוגע למימוש בדיוק לגבי הפרוייקט שלך, קשה לי להציע דרך גם בגלל שאני לא בקיא בו וגם בגלל שאני לא כ"כ בפרקטיקה של זה - ביישומים שלי אין כ"כ הרבה דרגות ואפשרויות. ההרשאות לטעמי לא צריכים להיות פר טבלה וסוג פעולה של קריאה/כתיבה, אלא פשוט פר פעולת לקוח. בקשה X שייכת רק למנהל, אז מוסיפים בה מידלוואר שבודק שיש הרשאות ניהול. אם בבקשה אחת יש אופציה לקבל מידע שונה לפי דרגת הניהול אין מנוס מלכתוב קוד קשיח יותר. -
@dovid
ראשית תודה רבה על התגובה המפורטת והארוכה.!@dovid אמר באימות משתמשים וממשק ניהול בנוד:
express-session.
אם אני מבין נכון (כך היה נדמה לי בניסוי מלמעלה), בכל הפעלה מחדש של השרת/אפליקציה זה מתאפס.
אני צודק?
ולכן זה בעייתי בשבילי, ובעיקר בתקופת הבניה, בו אני מאתחל די הרבה את האפליקציה לאחר כל שינוי. -
@dovid אמר באימות משתמשים וממשק ניהול בנוד:
יש בעיה שלקוח "ינחש" שסנים אחרים
אם אני מבין הספריה של express-session היא ס"ה להקל על הניהול של העוגיות, אבל בסופו של דבר בקטע האבטחה של ה"לנחש" עדיין אנו באותו מקום שהוא יוכל לזייף את העוגיה של express-session ואז הוא שוב מקבל הרשאת גישה.
או שיש כאן מנגנון הצפנה טוב יותר?עריכה:
אני מבין שיש כן קצת יותר אבטחה, שהמשתמש לא יכול לדעת איזה נתונים אתה שומר עליו, כי אתה מאחסן את המידע בשרת, וא"כ למשל אם אתה רוצה לשמור שהוא מחובר למספר מוסד XXX הוא לא יידע זאת.
אוקיי
אבל לעצם האבטחה שמישהו יקבל גישה לא מורשית לשרת באמצעות זיוף עוגיה, על זה נראה לי שאני עומד באותו מקום כמו בעוגיה רגילה.
תקן אותי אם אני טועה -
@yossiz אמר באימות משתמשים וממשק ניהול בנוד:
@חוקר יש הצפנה, express-session מקבלת כפרמטר secret שהוא מפתח ההצפנה:
בשורה אחרונה:
אם אני משתמש בעוגיות בלבד: חסרונות עלי ליצור טוקן מוצפן קשה לזיוף, עלי לנהל את הגדרות העוגיות, המידע (כל העדפות וכו' שאני שומר עליו) חשוף אצלי הלקוח.
אם אני משתמש ב express-session, זה מצפין עבורי מראש את העוגיה. (האם עלי ליצור טוקן, או שמספיק לי מזהה הפעלה פנימי שמשייך לי אותו למשתמש הנכון?), הגדרות הניהול הן יותר קלות, שאר המידע אינו נגיש ללקוח.
ישנו נתון נוסף? כתבתי יבש מידי כנראה.. -
@חוקר לא הבנתי אותך לגמרי.
א. מבחינתי אין שאלה בכלל האם להשתמש ב-node-session. ברור שכדאי להשתמש. לא רואה צד אחר.
ב.האם עלי ליצור טוקן, או שמספיק לי מזהה הפעלה פנימי שמשייך לי אותו למשתמש הנכון?
לא הבנתי את השאלה. node-session עושה עוגייה אחת אצל הלקוח, זה ה-sid (כלומר session id). ה-sid עצמו גם מוצפן. (למה? אני לא יודע, הרי אי אפשר לנחש sid של משתמש אחר, אולי כי ה-sid קצר אז אפשר לעשות מתקפת brute force). כל שאר ה-state שמשוייך לסשן נמצא ב-DB ו-node-session מצמיד אותו אוטומטי לאובייקט שאתה מקבל ב-
req.session
.
כל שעליך לעשות הוא, אחרי שאתה מקבל ומאמת פרטי כניסה, אתה מוסיף לאובייקט הסשן:
req.session.useId = xxx
ואז בכל בקשה שחייב אימות אתה כותב משהו בסגנון של:const isAuthenticated = (req, res, next) => { if (req.session.userId) { return next(); } return res.redirect('/login'); } app.get('/profile', isAuthenticated, (req, res) => { // אתה מגיע לפה רק אם אתה מאומת })
עבור logout אתה פשוט כותב:
req.session.userId = null;
כתבתי בקיצור, אם משהו לא מובן תשאל
אגב, לא העתקתי מקוד שאני משתמש בה, כי אני משתמש בספריית passport, אני לא יודע למה באמת והאם יש יתרון בו באימות פשוט של שם משתמש וסיסמה, אבל הוא תומך בעוד המון סוגי אימות.
-
@חוקר אמר באימות משתמשים וממשק ניהול בנוד:
אם אני מבין הספריה של express-session היא ס"ה להקל על הניהול של העוגיות,
לגמרי!
אבל בסופו של דבר בקטע האבטחה של ה"לנחש" עדיין אנו באותו מקום שהוא יוכל לזייף את העוגיה של express-session ואז הוא שוב מקבל הרשאת גישה.
בהחלט. ניחוש הוא גם דרך בטוחה לזכות בפייס... אתה קראת מה שכתבתי עם ה"קל לניחוש" מול ה"קשקוש"?
אבל לעצם האבטחה שמישהו יקבל גישה לא מורשית לשרת באמצעות זיוף עוגיה, על זה נראה לי שאני עומד באותו מקום כמו בעוגיה רגילה.
אני אכן דיברתי על עוגיה רגילה. עוגיה רגילה זה מאובטח ומצויין...
@חוקר אמר באימות משתמשים וממשק ניהול בנוד:
בשורה אחרונה:
אם אני משתמש בעוגיות בלבד: חסרונות עלי ליצור טוקן מוצפן קשה לזיוף, עלי לנהל את הגדרות העוגיות, המידע (כל העדפות וכו' שאני שומר עליו) חשוף אצלי הלקוח.ממש לא. גם אם אתה מממש לבד הכל בטוח וטוב (אם אתה עושה עם UUID כפי שאמרת בשאלה הפותחת + טבלה בצד שרת שמחזיקה UUID מול מזהה לקוח שלך - אחרי שהוא אימת את עצמו בשם וסיסמה). אתה מפסיד רק שאתה עובד קשה ופה ושם עושה פשלות ויש לך יותר קוד לתחזק.
אם אני משתמש ב express-session, זה מצפין עבורי מראש את העוגיה. (האם עלי ליצור טוקן, או שמספיק לי מזהה הפעלה פנימי שמשייך לי אותו למשתמש הנכון?),
יש פה אי הבנה. אני מקוה שמה ש@yossiz אמר הסביר לך מספיק, הספריה הזאת לא מתעסקת עם כלום. היא סה"כ דואגת שהאובייקט session שבrequest יישאר זהה לכל הבקשות מאותו משתמש בפרק זמן מוגדר. זהו.
את הכניסה בשם וסיסמה ואת "זכירת" איזה משתמש והעדפות צריך לעשות איך שבא לך ולשמור את ה"עולה לדינא" באובייקט session, ובו לבדוק לפי הפעולה מה צריך.
אני עייף אז אולי לא תבין אותי. -
@dovid אמר באימות משתמשים וממשק ניהול בנוד:
את הכניסה בשם וסיסמה ואת "זכירת" איזה משתמש והעדפות צריך לעשות איך שבא לך ולשמור את ה"עולה לדינא" באובייקט session, ובו לבדוק לפי הפעולה מה צריך.
את השמירה של העוגייה בצד לקוח, גם צריך לעשות,
או שזה כן נהיה לבד, וכל מה שצריך לעשות זה רק בשביל לדעת איך לנווט את המשתמש אחרי שזוהה?נ.ב. כמובן חוץ ממה שאמר @yossiz, שכשמקבלים session ריק - בלי user_Id אז צריך להכניס לו user_Id לפי השם משתמש והסיסמא - אם הם נכונים כמובן.
-
בעצם ה exspress-session הוא רק למשתמש יחיד?
כלומר אם שני אנשים עובדים מאותו מחשב, כל פעם שיחליפו, יצטרכו להכניס שם משתמש וסיסמא?
למשל אני עשיתי לבד כזה דבר,
כך נראית רשימת החיבורים, כמובן אם אופציה לניתוק החיבור בנפרד או מחיקת השם משתמש.
כך זה נשמר בדפדפן,
השאלה אם אני יוכל לעשות את אותו רעיון גם בספרייה הנ"ל.
-
@avi-rz ניכר משאלותיך שאתה מסתדר לא רע, אבל חסר לך ידע משלים בהבנת ארכיטקטורת הHTTP.
אני יותר מאשמח אם תפתח נושא ייעודי לזה, ושם אנסה לתת מדריך זוטא בעניין.
כדאי שתסביר בדיוק מה עשית, כדי שעצותיי יהיו טובות יותר מתוך הבנה טובה יותר איפה אתה נמצא.