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

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

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

סוגים של כללים
‎.read תיאור של הנסיבות שבהן משתמשים יכולים לקרוא את הנתונים.
‎.write מתאר אם ומתי הנתונים יכולים להיכתב.
‎.validate מגדירה איך ייראה ערך בפורמט תקין, אם יש לו מאפייני צאצא ואת סוג הנתונים.
‎.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.

כללי האבטחה של מסדי נתונים בזמן אמת כוללים משתנים מובנים ופונקציות שמאפשרות להפנות לנתיבים אחרים, לחותמות זמן בצד השרת, לפרטי אימות ועוד. זו דוגמה לכלל שמעניק למשתמשים מאומתים גישה לכתיבה ב-/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. דוגמה להצהרת אינדקס שתוסיף לאינדקס את השדות height ו-length של רשימה של דינוזאורים:

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

השלבים הבאים