כיצד פועלים כללי אבטחה

אבטחה יכולה להיות אחת החלקים המורכבים ביותר בפאזל לפיתוח אפליקציות. ברוב היישומים, על המפתחים לבנות ולהפעיל שרת המטפל באימות (מיהו משתמש) והרשאה (מה שמשתמש יכול לעשות).

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

בחר מוצר כדי ללמוד עוד על הכללים שלו.

ענן Firestore

מבנה בסיסי

כללי האבטחה של Firebase ב- Cloud Firestore וב- Cloud Storage משתמשים במבנה ובתחביר הבאים:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

חשוב להבין את מושגי המפתח הבאים בעת בניית הכללים:

  • בקשה: השיטה או השיטות להסתמך על allow בהצהרה. אלה שיטות שאתה מאפשר להפעיל. השיטות הסטנדרטיות הן: get , list , create , update , וכן delete . read ו write השיטות נוחות לאפשר גישת קריאה וכתיבה רחבה על נתיב נתון או אחסון שצוין.
  • נתיב: מיקום מסד הנתונים או אחסון, המיוצגת כנתיב URI.
  • כלל: allow אמירה, הכולל מצב המאפשר בקשה אם היא מעריכה אל נכון.

כללי אבטחה גרסה 2

החל ממאי 2019, גרסה 2 של כללי האבטחה של Firebase זמינה כעת. גרסה 2 של הכללים משנה את ההתנהגות של ג'וקר רקורסיבית {name=**} . עליך להשתמש בגרסת 2 אם בכוונתך להשתמש שאילתות קבוצה אוספות . עליך להצטרף כדי גירסה 2 על ידי ביצוע rules_version = '2'; השורה הראשונה בכללי האבטחה שלך:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

מסלולים תואמים

כל הצהרות ההתאמה צריכות להצביע על מסמכים, ולא על אוספים. הצהרה המשחק יכול להצביע על מסמך ספציפי, כמו match /cities/SF כלליים או שימוש כדי להצביע על כל מסמך בנתיב שצוין, כמו match /cities/{city} .

בדוגמה לעיל, הצהרת המשחק משתמשת {city} תחביר הכללי. אמצעי זה הכלל חל על כל מסמך של cities אוסף, כגון /cities/SF או /cities/NYC . כאשר allow ביטויים בדוח ההתאמה מוערכים, את city משתנה יפתור את שם המסמך העיר, כגון SF או NYC .

התאמת אוספי משנה

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

קחו למשל את המצב שבו כל מסמך cities אוסף המכיל landmarks subcollection. כללי אבטחה חלים רק על הנתיב המתאים, כך שולט הגישה מוגדרת על cities האוסף אינו חלים על landmarks subcollection. במקום זאת, כתוב כללים מפורשים כדי לשלוט בגישה לאוספי משנה:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      allow read, write: if <condition>;

        // Explicitly define rules for the 'landmarks' subcollection
        match /landmarks/{landmark} {
          allow read, write: if <condition>;
        }
    }
  }
}

כאשר קינון match הצהרות, את הנתיב של פנימית match ההצהרה הוא תמיד יחסים לנתיב של החיצוני match בהצהרה. לפיכך ערכות הכללים הבאות שוות ערך:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}
service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city}/landmarks/{landmark} {
      allow read, write: if <condition>;
    }
  }
}

כרטיסי בר רקורסיביים

אם אתה רוצה כללים שיחולו על היררכיה עמוקה באופן שרירותי, השתמש בתחביר הכללי רקורסיבית, {name=**} :

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

בעת שימוש בתחביר של תווים כלליים רקורסיביים, המשתנה של תווים כלליים יכיל את כל קטע הנתיב התואם, גם אם המסמך ממוקם בתת-אוסף מקונן עמוק. לדוגמא, הכללים המפורטים לעיל יתאימו מסמך הממוקם /cities/SF/landmarks/coit_tower , ואת הערך של document משתנה יהיה SF/landmarks/coit_tower .

שים לב, עם זאת, ההתנהגות של כרטיסי בר רקורסיביים תלויה בגרסת הכללים.

גרסה 1

כללי אבטחה משתמשים בגרסה 1 כברירת מחדל. בגרסה 1, תווים כלליים רקורסיביים תואמים פריט נתיב אחד או יותר. הם אינם תואמים שביל ריק, אז match /cities/{city}/{document=**} תואם מסמכים מהתת-אוספים אך לא cities אוספות, ואילו match /cities/{document=**} תואם הן מסמכים cities איסוף מהתת-אוספים.

כרטיסי בר רקורסיביים חייבים להגיע בסוף הצהרת משחק.

גרסה 2

בגרסה 2 של כללי האבטחה, תווים כלליים רקורסיביים תואמים לאפס פריטי נתיב או יותר. match/cities/{city}/{document=**} תואם מסמכים בכול מהתת-אוספים, כמו גם מסמכי cities האוספים.

עליך להצטרף כדי גירסה 2 על ידי הוספת rules_version = '2'; בראש כללי האבטחה שלך:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{city}/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

אתה יכול לכלול לכל היותר תו-כללי רקורסיבי לכל הצהרת התאמה, אך בגרסה 2 תוכל למקם תו-כללי זה בכל מקום בהצהרת ההתאמה. לדוגמה:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the songs collection group
    match /{path=**}/songs/{song} {
      allow read, write: if <condition>;
    }
  }
}

אם אתה משתמש שאילתות קבוצה אוספות , עליך להשתמש בגרסה 2, רואה באבטחת שאילתות קבוצה אוספת .

הצהרות התאמה חופפות

זה אפשרי עבור מסמך להתאים יותר מאחד match בהצהרה. במקרה שבו המספר allow ביטויים להתאים בקשה, הגישה מותרת אם אחד מהתנאים הוא true :

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the 'cities' collection.
    match /cities/{city} {
      allow read, write: if false;
    }

    // Matches any document in the 'cities' collection or subcollections.
    match /cities/{document=**} {
      allow read, write: if true;
    }
  }
}

בדוגמא לעיל, כול קריאה וכתיבה אל cities אוספות תוותר כי הכלל השני הוא תמיד true , למרות הכלל הראשון הוא תמיד false .

מגבלות כלל האבטחה

כשאתה עובד עם כללי אבטחה, שים לב למגבלות הבאות:

לְהַגבִּיל פרטים
מספר מרבי של exists() , get() , ולאחר getAfter() קוראת לכל בקשה
  • 10 לבקשות ומסמכים בודדים ובקשות שאילתה.
  • 20 לקריאות, עסקאות וכתיבת קבוצות מרובות מסמכים. המגבלה הקודמת של 10 חלה גם על כל פעולה.

    לדוגמה, דמיין שאתה יוצר בקשת כתיבה קבוצה עם 3 פעולות כתיבה ושכללי האבטחה שלך משתמשים בשתי שיחות גישה למסמכים כדי לאמת כל כתיבה. במקרה זה, כל כתיבה משתמשת ב -2 מתוך עשר שיחות הגישה שלה ובקשת הכתיבה באצווה משתמשת ב -6 מתוך 20 שיחות הגישה שלה.

חריגה משתי המגבלות גורמת לשגיאה שנדחתה.

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

מקוננות מקסימלי match לעומק הצהרה 10
אורך שביל מקסימאלי, פלחי נתיב, מותר בתוך קבוצה של מקוננות match דוחה 100
מספר מרבי של משתנה ללכוד נתיב מותר בתוך קבוצה של מקוננות match דוחה 20
עומק שיחת פונקציה מרבי 20
מספר מרבי של ארגומנטים של פונקציות 7
מספר מרבי של let איגודי משתנה לכל פונקציה 10
מספר מרבי של שיחות פונקציה רקורסיביות או מחזוריות 0 (אסור)
מספר מקסימלי של ביטויים שהוערך לפי בקשה 1,000
גודל מקסימלי של מערכת חוקים ערכות הכללים חייבות לציית לשתי מגבלות גודל:
  • מגבלת 256 KB בגודל של מקור טקסט מערכת הכללים שפורסם מתוך Firebase הקונסולה או מן CLI באמצעות firebase deploy .
  • מגבלה של 250 KB בגודל מערך הכללים המהולל שנוצר כאשר Firebase מעבד את המקור והופך אותו לפעיל במערך האחורי.

אחסון בענן

מבנה בסיסי

כללי האבטחה של Firebase ב- Cloud Firestore וב- Cloud Storage משתמשים במבנה ובתחביר הבאים:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

חשוב להבין את מושגי המפתח הבאים בעת בניית הכללים:

  • בקשה: השיטה או השיטות להסתמך על allow בהצהרה. אלה שיטות שאתה מאפשר להפעיל. השיטות הסטנדרטיות הן: get , list , create , update , וכן delete . read ו write השיטות נוחות לאפשר גישת קריאה וכתיבה רחבה על נתיב נתון או אחסון שצוין.
  • נתיב: מיקום מסד הנתונים או אחסון, המיוצגת כנתיב URI.
  • כלל: allow אמירה, הכולל מצב המאפשר בקשה אם היא מעריכה אל נכון.

מסלולים תואמים

אחסון ענן אבטחה חוקי match את נתיבי קובץ המשמש גישה לקבצים ב- Cloud Storage. כללים יכולים match נתיבים מדויקים או נתיבים כלליים, ותקנון יכול גם להיות מקונן. אם אין כלל התאמה מאפשרת שיטת בקשה, או מעריכת תנאי false , הבקשה נדחית.

התאמות מדויקות

// Exact match for "images/profilePhoto.png"
match /images/profilePhoto.png {
  allow write: if <condition>;
}

// Exact match for "images/croppedProfilePhoto.png"
match /images/croppedProfilePhoto.png {
  allow write: if <other_condition>;
}

גפרורים מקוננים

// Partial match for files that start with "images"
match /images {
  // Exact match for "images/profilePhoto.png"
  match /profilePhoto.png {
    allow write: if <condition>;
  }

  // Exact match for "images/croppedProfilePhoto.png"
  match /croppedProfilePhoto.png {
    allow write: if <other_condition>;
  }
}

משחקי תווים כלליים

כללים יכולים לשמש גם כדי match דפוס שימוש בתווים כלליים. תו כללי הוא משתנה בשם שמייצג גם מחרוזת אחת כגון profilePhoto.png , או מספר מקטעי נתיב, כגון images/profilePhoto.png .

תו כללי נוצר על ידי הוספת סוגריים מסולסלים סביב השם הכללי, כמו {string} . תו כללי מגזר מרובה יכול להיות מוצהר על ידי הוספה =** לשם הכלליים, כמו {path=**} :

// Partial match for files that start with "images"
match /images {
  // Exact match for "images/*"
  // e.g. images/profilePhoto.png is matched
  match /{imageId} {
    // This rule only matches a single path segment (*)
    // imageId is a string that contains the specific segment matched
    allow read: if <condition>;
  }

  // Exact match for "images/**"
  // e.g. images/users/user:12345/profilePhoto.png is matched
  // images/profilePhoto.png is also matched!
  match /{allImages=**} {
    // This rule matches one or more path segments (**)
    // allImages is a path that contains all segments matched
    allow read: if <other_condition>;
  }
}

אם מספר כללים להתאים לקובץ, התוצאה היא OR של התוצאה של כל הערכות הכללים. כלומר, אם בכלל כלל הקובץ מתאים evalutes כדי true , התוצאה היא true .

בשנת הכללים לעיל, את הקובץ "תמונות / profilePhoto.png" ניתן לקרוא אם מתקיימים condition או other_condition להעריך אל נכון, בעוד הקובץ "images / משתמשים / משתמש: 12,345 / profilePhoto.png" כפוף רק התוצאה של other_condition .

משתנים כללי ניתן להפנות אליהם מתוך match לספק שם קובץ או אישור נתיב:

// Another way to restrict the name of a file
match /images/{imageId} {
  allow read: if imageId == "profilePhoto.png";
}

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

בקש הערכה

העלאות, הורדות, שינויי metadata, ותמחק מוערכות באמצעות request נשלחת לאחסון בענן. request המשתנה מכיל את נתיב הקובץ שבו הבקשה מתבצעת, הפעם כאשר קבלת הבקשה, ואת החדש resource הערך אם הבקשה היא כתיבה. כותרות HTTP ומצב אימות כלולים גם כן.

request האובייקט מכיל גם את המזהה הייחודית של המשתמש, ומטען אימות Firebase ב request.auth האובייקט, אשר יוסבר נוסף אימות קטע Docs.

רשימה מלאה של נכסי request האובייקט זמינה להלן:

תכונה סוּג תיאור
auth מפה <מחרוזת, מחרוזת> כשמשתמש נכנס לאתר, מספק uid , מזהה ייחודי של המשתמש, וכן token , מפת תביעות JWT אימות Firebase. אחרת, זה יהיה null .
params מפה <מחרוזת, מחרוזת> מפה המכילה את פרמטרי השאילתה של הבקשה.
path נָתִיב path המייצג את נתיב הבקשה מתבצעת בבית.
resource מפה <מחרוזת, מחרוזת> שווי המשאב החדש, מציג רק על write בקשות.
time חותמת זמן חותמת זמן המייצגת את זמן השרת בו מבקשים את הבקשה.

הערכת משאבים

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

אבטחת Firebase כללי אחסון הענן מספקים metadata קובץ resource האובייקט, אשר מכיל זוגות ערך / מפתח של metadata ועלו באובייקט אחסון בענן. ניתן לבדוק תכונות אלו על read או write בקשות כדי להבטיח שלמות הנתונים.

על write בקשות (למשל העלאות, עדכוני metadata, ומחיקות), בנוסף resource האובייקט, אשר מכיל מידע נוסף על קובץ עבור הקובץ שקיים כיום בנתיב הבקשה, יש לך גם את היכולת להשתמש request.resource האובייקט, שמכיל תת-קבוצה של מטא-הנתונים של הקובץ שייכתב אם הכתיבה מותרת. באפשרותך להשתמש בשני הערכים הללו כדי להבטיח שלמות נתונים או לאכוף מגבלות יישומים כגון סוג קובץ או גודל.

רשימה מלאה של נכסי resource האובייקט זמינה להלן:

תכונה סוּג תיאור
name חוּט השם המלא של האובייקט
bucket חוּט שם הדלי בו שוכן האובייקט.
generation int דור אובייקט Google Cloud Storage של האובייקט הזה.
metageneration int Metageneration אובייקט Google Cloud Storage של האובייקט הזה.
size int גודל האובייקט בתים.
timeCreated חותמת זמן חותמת זמן המייצגת את הזמן בו נוצר אובייקט.
updated חותמת זמן חותמת זמן המייצגת את הזמן שבו אובייקט עודכן לאחרונה.
md5Hash חוּט חשיש MD5 של האובייקט.
crc32c חוּט חשיש crc32c של האובייקט.
etag חוּט ה- etag הקשור לאובייקט זה.
contentDisposition חוּט נטיית התוכן הקשורה לאובייקט זה.
contentEncoding חוּט קידוד התוכן המשויך לאובייקט זה.
contentLanguage חוּט שפת התוכן המשויכת לאובייקט זה.
contentType חוּט סוג התוכן המשויך לאובייקט זה.
metadata מפה <מחרוזת, מחרוזת> זוגות מפתח / ערך של מטא נתונים מותאמים אישית נוספים שצוינו על ידי מפתח.

request.resource מכיל את כל אלה, למעט generation , metageneration , etag , timeCreated , ו updated .

דוגמא מלאה

אם מצרפים את הכל, תוכלו ליצור דוגמה מלאה לכללים לפתרון אחסון תמונות:

service firebase.storage {
 match /b/{bucket}/o {
   match /images {
     // Cascade read to any image type at any path
     match /{allImages=**} {
       allow read;
     }

     // Allow write files to the path "images/*", subject to the constraints:
     // 1) File is less than 5MB
     // 2) Content type is an image
     // 3) Uploaded content type matches existing content type
     // 4) File name (stored in imageId wildcard variable) is less than 32 characters
     match /{imageId} {
       allow write: if request.resource.size < 5 * 1024 * 1024
                    && request.resource.contentType.matches('image/.*')
                    && request.resource.contentType == resource.contentType
                    && imageId.size() < 32
     }
   }
 }
}

מסד נתונים בזמן אמת

מבנה בסיסי

במסד נתונים בזמן אמת, כללי האבטחה של Firebase כוללים ביטויים דמויי JavaScript הכלולים במסמך JSON.

הם משתמשים בתחביר הבא:

{
  "rules": {
    "<<path>>": {
    // Allow the request if the condition for each method is true.
      ".read": <<condition>>,
      ".write": <<condition>>,
      ".validate": <<condition>>
    }
  }
}

ישנם שלושה אלמנטים בסיסיים בכלל:

  • נתיב: מיקום מסד הנתונים. זה משקף את מבנה JSON של מסד הנתונים שלך.
  • בקשה: אלו הם שיטות השימושים כלל להעניק גישה. read ו write הכללים להעניק לקריאה רחבה גישה לכתיבה, תוך validate כללים לשמש לאימות משנית גישה מענק המבוססים על נתונים נכנסים או קיימים.
  • מצב: מצב המאפשר בקשה אם היא מעריכה אל נכון.

כיצד חלים כללים על שבילים

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

שקול את הכללים הבאים:

{
  "rules": {
     "foo": {
        // allows read to /foo/*
        ".read": "data.child('baz').val() === true",
        "bar": {
          // ignored, since read was allowed already
          ".read": false
        }
     }
  }
}

מבנה ביטחון זה מאפשר /bar/ שייקרא מן האימה /foo/ מכיל ילד baz עם ערך true . ".read": false כלל תחת /foo/bar/ אין השפעה כאן, מאז הגישה לא יכול לשלול נתיב ילד.

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

עם זאת, .validate הכללים לא מפל. יש לאפשר את כל כללי האימות בכל רמות ההיררכיה כדי שניתן יהיה לכתוב.

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

{
  "rules": {
    "records": {
      "rec1": {
        ".read": true
      },
      "rec2": {
        ".read": false
      }
    }
  }
}

מבלי להבין כי הכללים נבדקים אטומית, זה אולי נראה כמו שליפת /records/ נתיב יחזור rec1 אבל לא rec2 . אולם התוצאה בפועל היא שגיאה:

JavaScript
var db = firebase.database();
db.ref("records").once("value", function(snap) {
  // success method is not called
}, function(err) {
  // error callback triggered with PERMISSION_DENIED
});
מטרה-ג
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[_ref child:@"records"] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
  // success block is not called
} withCancelBlock:^(NSError * _Nonnull error) {
  // cancel block triggered with PERMISSION_DENIED
}];
מָהִיר
var ref = FIRDatabase.database().reference()
ref.child("records").observeSingleEventOfType(.Value, withBlock: { snapshot in
    // success block is not called
}, withCancelBlock: { error in
    // cancel block triggered with PERMISSION_DENIED
})
ג'אווה
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("records");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot snapshot) {
    // success method is not called
  }

  @Override
  public void onCancelled(FirebaseError firebaseError) {
    // error callback triggered with PERMISSION_DENIED
  });
});
מנוחה
curl https://docs-examples.firebaseio.com/rest/records/
# response returns a PERMISSION_DENIED error

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

Attempt to read /records with auth=Success(null)
    /
    /records

No .read rule allowed the operation.
Read was denied.

המבצע נדחה משום שלא כלל לקרוא מורשה לגשת /records/ נתיב, אך מציין כי הכלל עבור rec1 מעולם הוערך כי זה לא היה בנתיב בקשנו. כדי להביא rec1 , היינו צריכים לגשת אליו ישירות:

JavaScript
var db = firebase.database();
db.ref("records/rec1").once("value", function(snap) {
  // SUCCESS!
}, function(err) {
  // error callback is not called
});
מטרה-ג
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
    // SUCCESS!
}];
מָהִיר
var ref = FIRDatabase.database().reference()
ref.child("records/rec1").observeSingleEventOfType(.Value, withBlock: { snapshot in
    // SUCCESS!
})
ג'אווה
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("records/rec1");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot snapshot) {
    // SUCCESS!
  }

  @Override
  public void onCancelled(FirebaseError firebaseError) {
    // error callback is not called
  }
});
מנוחה
curl https://docs-examples.firebaseio.com/rest/records/rec1
# SUCCESS!

משתנה מיקום

כללי מסד זמן אמת לתמוך $location משתנה כדי להתאים מקטעי נתיב. השתמש $ קידומת מול פלח הנתיב שלך כדי להתאים את הכלל לכל הצמתים הילד לאורך השביל.

  {
    "rules": {
      "rooms": {
        // This rule applies to any child of /rooms/, the key for each room id
        // is stored inside $room_id variable for reference
        "$room_id": {
          "topic": {
            // The room's topic can be changed if the room id has "public" in it
            ".write": "$room_id.contains('public')"
          }
        }
      }
    }
  }

אתה יכול גם להשתמש $variable במקביל שמות נתיב קבוע.

  {
    "rules": {
      "widget": {
        // a widget can have a title or color attribute
        "title": { ".validate": true },
        "color": { ".validate": true },

        // but no other child paths are allowed
        // in this case, $other means any key excluding "title" and "color"
        "$other": { ".validate": false }
      }
    }
  }