אבטחה היא אחד החלקים המורכבים ביותר בפאזל של פיתוח אפליקציות. ברוב האפליקציות, המפתחים צריכים ליצור ולהפעיל שרת שמטפל באימות (מי המשתמש) ובהרשאה (מה המשתמש יכול לעשות).
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>>
}
}
חשוב להבין את מושגי המפתח הבאים כשאתם יוצרים את הכללים:
- Request: השיטות שהופעלו בהצהרה
allow
. אלה השיטות שאתם מאפשרים להריץ. השיטות הרגילות הן:get
,list
,create
,update
ו-delete
. שיטות הנוחותread
ו-write
מאפשרות גישה רחבה לקריאה ולכתיבה במסד הנתונים או בנתיב האחסון שצוינו. - נתיב: מסד הנתונים או מיקום האחסון, שמיוצגים כנתיב URI.
- כלל: משפט
allow
, שכולל תנאי שמאפשר בקשה אם הוא מקבל ערך True.
כללי אבטחה בגרסה 2
החל ממאי 2019, גרסה 2 של כללי האבטחה של Firebase זמינה עכשיו. בגרסה 2 של הכללים יש שינוי בהתנהגות של סמלי Wildcard רפרסיביים {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
.
עם זאת, חשוב לזכור שההתנהגות של תווים כלליים חזרה (recursive) תלויה בגרסה של הכללים.
גרסה 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() בכל בקשה |
אם חורגים מאחד מהגבולות האלה, מתקבלת הודעת שגיאה מסוג 'הרשאה נדחתה'. יכול להיות שחלק מהקריאות לגישה למסמכים יישמרו במטמון, קריאות כאלה לא נספרות במסגרת המגבלות. |
עומק הקינון המקסימלי של משפטי match |
10 |
אורך הנתיב המקסימלי, בקטעי נתיב, שמותר בקבוצה של משפטי match בתצוגת עץ |
100 |
המספר המקסימלי של משתני תיעוד נתיב שמותר להשתמש בהם בתוך קבוצה של משפטי match בתצוגת עץ |
20 |
עומק קריאה מקסימלי של פונקציה | 20 |
מספר הארגומנטים המקסימלי של פונקציה | 7 |
המספר המקסימלי של קישורי משתני let לכל פונקציה |
10 |
המספר המקסימלי של קריאות פונקציה חזרותיות או מחזוריות | 0 (not permitted) |
המספר המקסימלי של ביטויים שאפשר להעריך בכל בקשה | 1,000 |
הגודל המקסימלי של קבוצת כללים | קבוצות הכללים חייבות לעמוד בשני מגבלות גודל:
|
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>>
}
}
חשוב להבין את מושגי המפתח הבאים כשאתם יוצרים את הכללים:
- Request: השיטות שהופעלו בהצהרה
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
:
// 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 , מפה של Firebase Authentication הצהרות JWT. אחרת, הערך יהיה 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 |
מחרוזת | גיבוב (hash) MD5 של האובייקט. |
crc32c |
מחרוזת | גיבוב CRC32C של האובייקט. |
etag |
מחרוזת | ה-etag שמשויך לאובייקט הזה. |
contentDisposition |
מחרוזת | אופן הטיפול בתוכן שמשויך לאובייקט הזה. |
contentEncoding |
מחרוזת | קידוד התוכן שמשויך לאובייקט הזה. |
contentLanguage |
מחרוזת | שפת התוכן שמשויכת לאובייקט הזה. |
contentType |
מחרוזת | סוג התוכן שמשויך לאובייקט הזה. |
metadata |
map<string, string> | צמדי מפתח/ערך של מטא-נתונים מותאמים אישית נוספים שצוינו על ידי המפתח. |
השדה request.resource
מכיל את כל הערכים האלה, מלבד generation
, metageneration
, etag
, timeCreated
ו-updated
.
מגבלות על כללי אבטחה
כשעובדים עם כללי אבטחה, חשוב לשים לב למגבלות הבאות:
מגבלה | פרטים |
---|---|
המספר המקסימלי של קריאות firestore.exists() ו-firestore.get() לכל בקשה |
2 לבקשות של מסמך יחיד ולבקשות של שאילתות. אם חורגים מהמגבלה הזו, תופיע שגיאה מסוג permission denied. יכול להיות שקריאות גישה לאותו מסמך יישמרו במטמון, וקריאות במטמון לא נספרות במסגרת המגבלות. |
דוגמה מלאה
אם משלבים את כל הרכיבים האלה, אפשר ליצור דוגמה מלאה לכללים לפתרון אחסון תמונות:
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 } } } }
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 של מסד הנתונים.
- Request:אלה השיטות שבהן הכלל משתמש כדי להעניק גישה. הכללים
read
ו-write
מעניקים גישה רחבה לקריאה ולכתיבה, בעוד שהכלליםvalidate
משמשים לאימות משני כדי להעניק גישה על סמך נתונים נכנסים או קיימים. - Condition: התנאי שמאפשר בקשה אם הערך המחושב שלו הוא 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
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
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
FIRDatabaseReference *ref = [[FIRDatabase database] reference]; [[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // SUCCESS! }];
Swift
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 }
}
}
}