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

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

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

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

Cloud 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 .

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

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

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

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 קריאות גישה למסמכים כדי לאמת כל כתיבה. במקרה זה, כל כתיבה משתמשת ב-2 מתוך 10 שיחות הגישה שלה ובקשת הכתיבה המצטברת משתמשת ב-6 מתוך 20 שיחות הגישה שלה.

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

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

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

נתיבים תואמים

כללי האבטחה של Cloud Storage 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 .

בכללים שלמעלה, ניתן לקרוא את הקובץ "images/profilePhoto.png" אם condition או other_condition מוערכים כ-true, בעוד שהקובץ "images/users/user:12345/profilePhoto.png" כפוף רק לתוצאה של other_condition .

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

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

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

בקש הערכה

העלאות, הורדות, שינויים במטא נתונים ומחיקות מוערכים באמצעות request הנשלחת ל-Cloud Storage. משתנה request מכיל את נתיב הקובץ שבו מתבצעת הבקשה, את השעה שבה הבקשה מתקבלת וערך resource החדש אם הבקשה היא כתיבה. כותרות HTTP ומצב אימות כלולים גם כן.

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

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

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

הערכת משאבים

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

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

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

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

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

request.resource מכיל את כל אלה למעט generation , מטא etag metageneration 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
});
Objective-C
הערה: מוצר Firebase זה אינו זמין ביעד App Clip.
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
}];
מָהִיר
הערה: מוצר Firebase זה אינו זמין ביעד App Clip.
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
})
Java
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
});
Objective-C
הערה: מוצר Firebase זה אינו זמין ביעד App Clip.
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
    // SUCCESS!
}];
מָהִיר
הערה: מוצר Firebase זה אינו זמין ביעד App Clip.
var ref = FIRDatabase.database().reference()
ref.child("records/rec1").observeSingleEventOfType(.Value, withBlock: { snapshot in
    // SUCCESS!
})
Java
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 }
      }
    }
  }