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

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

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

בוחרים מוצר כדי לקבל מידע נוסף על הכללים שלו.

Cloud Firestore

מבנה בסיסי

Firebase Security Rules ב-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, שכוללת תנאי שמאפשר בקשה אם הערך המחושב שלו הוא True.

כללי אבטחה גרסה 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>;
    }
  }
}

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

יכול להיות שמסמך יתאים ליותר מהצהרה אחת.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.
    match /cities/{document} {
      allow read, write: if true;
    }
  }
}

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

תווים כלליים לחיפוש רקורסיבי

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

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

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

מגבלה פרטים
מספר השיחות המקסימלי עם 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
הגודל המקסימלי של קבוצת כללים יש שני מגבלות גודל שחלות על קבוצות כללים:
  • הגבלה של 256KB על הגודל של מקור הטקסט של קבוצת הכללים שפורסמה ממסוף Firebase או מ-CLI באמצעות firebase deploy.
  • מגבלה של 250KB על הגודל של קבוצת הכללים המהודרת שמתקבלת כש-Firebase מעבד את המקור והופך אותו לפעיל בשרת העורפי.

Cloud Storage

מבנה בסיסי

Firebase Security Rules ב-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, שכוללת תנאי שמאפשר בקשה אם הערך המחושב שלו הוא True.

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

Cloud Storage Security Rules 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 של תוצאת כל הערכות של הכללים. כלומר, אם יש כלל שהקובץ תואם לו והערך שלו הוא true, התוצאה היא true.

בכללים, אפשר לקרוא את הקובץ images/profilePhoto.png אם הביטוי condition או הביטוי other_condition מחזירים את הערך true, אבל הקובץ images/users/user:12345/profilePhoto.png כפוף רק לתוצאה של הביטוי other_condition.

אפשר להפנות למשתנה כללי מתוך match provide filename או הרשאת נתיב:

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

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

בקשת הערכה

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

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

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

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

הערכת משאבים

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

Firebase Security Rules עבור 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 מחרוזת גיבוב MD5 של האובייקט.
crc32c מחרוזת גיבוב (hash) מסוג crc32c של האובייקט.
etag מחרוזת תג ה-etag שמשויך לאובייקט הזה.
contentDisposition מחרוזת המאפיין content-disposition שמשויך לאובייקט הזה.
contentEncoding מחרוזת קידוד התוכן שמשויך לאובייקט הזה.
contentLanguage מחרוזת שפת התוכן שמשויכת לאובייקט הזה.
contentType מחרוזת סוג התוכן שמשויך לאובייקט הזה.
metadata map<string, string> צמדי מפתח/ערך של מטא-נתונים מותאמים אישית נוספים שצוינו על ידי מפתח.

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

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

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

מגבלה פרטים
מספר השיחות המקסימלי של firestore.exists() ושל firestore.get() לכל בקשה

‫2 לבקשות של מסמך יחיד ולבקשות של שאילתות.

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

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

דוגמה מלאה

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

service firebase.storage {
 match /b/{bucket}/o {
   match /images {
     // 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) Filename (stored in imageId wildcard variable) is less than 32 characters
     match /{imageId} {
       allow read;
       allow write: if request.resource.size < 5 * 1024 * 1024
                    && request.resource.contentType.matches('image/.*')
                    && request.resource.contentType == resource.contentType
                    && imageId.size() < 32
     }
   }
 }
}

Realtime Database

מבנה בסיסי

ב-Realtime Database, ‏Firebase Security Rules מורכבים מביטויים דמויי 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 פועלים כאימות משני כדי להעניק גישה על סמך נתונים קיימים או נתונים נכנסים.
  • תנאי: התנאי שמאפשר את הבקשה אם הערך שלו הוא True.

איך הכללים חלים על נתיבים

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

כדאי להביא בחשבון את הכללים הבאים:

{
  "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
}];
Swift
הערה: מוצר 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
  });
});
REST
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!
}];
Swift
הערה: מוצר 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
  }
});
REST
curl https://docs-examples.firebaseio.com/rest/records/rec1
# SUCCESS!

משתנה מיקום

Realtime Database Rules תומכים ב$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 }
      }
    }
  }