הסבר על כללי האבטחה של מסד הנתונים בזמן אמת ב-Firebase

כללי האבטחה של Firebase Realtime Database קובעים למי יש גישה לקריאה ולכתיבה במסד הנתונים, איך הנתונים מובְנים ואילו אינדקסים קיימים. הכללים האלה נמצאים בשרתים של Firebase והם נאכפים באופן אוטומטי בכל שלב. כל קריאה ובקשת הכתיבה תושלם רק אם הכללים שלך יאפשרו זאת. כברירת מחדל, הכללים שלכם לא מאפשרים לאף אחד לגשת למסד הנתונים שלכם. המטרה היא להגן על מניצול לרעה, עד שיהיה לכם זמן להתאים אישית את הכללים או להגדיר אימות.

לכללי האבטחה של מסדי נתונים בזמן אמת יש תחביר דמוי JavaScript, והם כוללים ארבעה סוגים:

סוגי כללים
‎.read המדיניות קובעת אם ומתי המשתמשים יכולים לקרוא נתונים.
‎.write מתאר אם ומתי הנתונים יכולים להיכתב.
.verify מגדיר את המראה של ערך בפורמט תקין, אם יש לו מאפייני צאצא וסוג הנתונים.
.indexOn מציינת צאצא להוספה לאינדקס כדי לתמוך בהזמנה ובשאילתות.

Realtime Database סקירה כללית על אבטחה

ב-Firebase Realtime Database יש קבוצה מלאה של כלים לניהול האבטחה של האפליקציה. בעזרת הכלים האלה קל לאמת את המשתמשים, לאכוף את הרשאות המשתמשים ולאמת את הקלט.

באפליקציות שמבוססות על Firebase פועל יותר קוד בצד הלקוח בהשוואה לאפליקציות עם סטאקים רבים אחרים של טכנולוגיות. לכן, הגישה שלנו לאבטחה עשויה להיות שונה ממה שאתם רגילים אליו.

אימות

שלב ראשון נפוץ באבטחת האפליקציה הוא לזיהוי המשתמשים. התהליך הזה נקרא אימות. אתם יכולים להשתמש באימות ב-Firebase כדי לאפשר למשתמשים להיכנס לאפליקציה. אימות ב-Firebase כולל תמיכה בשיטות אימות נפוצות כמו Google ו-Facebook, וגם כניסה באמצעות אימייל וסיסמה, כניסה אנונימית ועוד.

זהות משתמש היא קונספט אבטחה חשוב. למשתמשים שונים יש נתונים שונים, ולפעמים יש להם יכולות שונות. לדוגמה, באפליקציית צ'אט, כל הודעה משויכת למשתמש שיצר אותה. יכול להיות שהמשתמשים יוכלו למחוק גם את ההודעות שלהם, אבל לא הודעות שפורסמו על ידי משתמשים אחרים.

הרשאה

זיהוי המשתמש הוא רק חלק מאבטחה. אחרי שתזהו את המשתמשים, תצטרכו למצוא דרך לשלוט בגישה שלהם לנתונים במסד הנתונים. כללי האבטחה של מסדי הנתונים בזמן אמת מאפשרים לכם לשלוט בגישה של כל משתמש. לדוגמה, הנה סדרה של כללי אבטחה שמאפשרים לכל אחד לקרוא את הנתיב /foo/, אבל לא אחת לכתוב לה:

{
  "rules": {
    "foo": {
      ".read": true,
      ".write": false
    }
  }
}

הכללים .read ו-.write פועלים ברצף, כך שמערכת הכללים הזו מעניקה גישה לקריאה לכל הנתונים בנתיב /foo/ וגם לנתיבי עומק יותר, כמו /foo/bar/baz. חשוב לזכור שכללי .read ו-.write שנמצאים בחלק העליון של מסד הנתונים מבטלים כללים שנמצאים בחלק התחתון, כך שגישת קריאה ל-/foo/bar/baz עדיין תתקבל בדוגמה הזו גם אם כלל בנתיב /foo/bar/baz הוערך כ-false.

כללי האבטחה של Realtime Database כוללים משתנים מובנים ופונקציות שמאפשרות להפנות לנתיבים אחרים, לחותמות זמן בצד השרת, לפרטי אימות ועוד. זוהי דוגמה לכלל שמעניק למשתמשים מאומתים גישה לכתיבה ב-/users/<uid>/, כאשר <uid> הוא המזהה של המשתמש שהתקבל דרך Firebase Authentication.

{
  "rules": {
    "users": {
      "$uid": {
        ".write": "$uid === auth.uid"
      }
    }
  }
}

אימות נתונים

הקובץ Firebase Realtime Database ללא סכימה. כך קל לשנות דברים במהלך הפיתוח, אבל ברגע שהאפליקציה מוכנה להפצה, חשוב כדי לשמור על עקביות. שפת הכללים כוללת את הטקסט .validate כלל שמאפשר להחיל לוגיקת אימות באמצעות אותם ביטויים שבהם נעשה שימוש לכללים .read ו-.write. ההבדל היחיד הוא שכללי האימות לא מדורגים, כך שכל הכללים הרלוונטיים כללי האימות חייבים לקבל ערך True כדי שהכתיבה תאושר.

לפי הכלל הזה, הנתונים שנכתבו אל /foo/ חייבים להיות מחרוזת באורך של פחות מ-100 תווים:

{
  "rules": {
    "foo": {
      ".validate": "newData.isString() && newData.val().length < 100"
    }
  }
}

לכללי האימות יש גישה לכל הפונקציות המובנות, משתנים בתור הכללים .read ו-.write. אפשר להשתמש כדי ליצור כללי אימות שמודעים לנתונים שנמצאים במקומות אחרים מסד הנתונים, זהות המשתמש, זמן השרת ועוד הרבה יותר.

הגדרת אינדקסים של מסדי נתונים

Firebase Realtime Database מאפשר למיין נתונים ולהריץ שאילתות עליהם. במסדי נתונים עם נפח נתונים קטן, יש תמיכה בשאילתות אד-הוק, ולכן בדרך כלל אין צורך באינדקסים במהלך הפיתוח. עם זאת, לפני שמפעילים את האפליקציה, כדי לציין אינדקסים לשאילתות שלך כדי להבטיח שהם ימשיכו לפעול שהאפליקציה שלכם גדלה.

אפשר לציין את האינדקסים באמצעות הכלל .indexOn. כאן מוצגת דוגמה שלגביה תיצור אינדקס של שדות הגובה והאורך לרשימה של דינוזאורים:

{
  "rules": {
    "dinosaurs": {
      ".indexOn": ["height", "length"]
    }
  }
}

השלבים הבאים