כללי האבטחה של Firebase ממנפים שפות גמישות, חזקות ומותאמות אישית התומכות במגוון רחב של מורכבות ופירוט. אתה יכול להגדיר את הכללים שלך ספציפיים או כלליים ככל שהגיוני עבור האפליקציה שלך. חוקי מסד נתונים בזמן אמת משתמשים בתחביר שנראה כמו JavaScript במבנה JSON. כללי Cloud Firestore ו-Cloud Storage משתמשים בשפה המבוססת על שפת הביטוי Common (CEL) , שמתבססת על CEL עם match
allow
הצהרות התומכות בגישה מוענקת על תנאי.
עם זאת, מכיוון שמדובר בשפות מותאמות אישית, יש עקומת למידה. השתמש במדריך זה כדי להבין טוב יותר את שפת הכללים ככל שאתה צולל עמוק יותר לתוך כללים מורכבים יותר.
בחר מוצר כדי ללמוד עוד על הכללים שלו.
מבנה בסיסי
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
, הכוללת תנאי שמתיר בקשה אם היא מוערכת כאמת.
כל אחד מהמושגים הללו מתואר בפירוט נוסף להלן.
אחסון בענן
כללי האבטחה של 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
, הכוללת תנאי שמתיר בקשה אם היא מוערכת כאמת.
כל אחד מהמושגים הללו מתואר בפירוט נוסף להלן.
מסד נתונים בזמן אמת
במסד נתונים בזמן אמת, כללי האבטחה של 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
פועלים כאימות משני להענקת גישה על סמך נתונים נכנסים או קיימים. - תנאי: התנאי שמתיר בקשה אם היא מוערכת כנכונה.
בונה כללים
Cloud Firestore
המרכיבים הבסיסיים של כלל ב-Cloud Firestore ו-Cloud Storage הם כדלקמן:
- הצהרת
service
: מצהירה על מוצר Firebase שהכללים חלים עליו. - בלוק
match
: מגדיר נתיב במסד הנתונים או בדלי האחסון שעליהם חלים הכללים. - הצהרת
allow
: מספקת תנאים למתן גישה, מובחנים לפי שיטות. השיטות הנתמכות כוללות:get
,list
,create
,update
,delete
ושיטות הנוחותread
write
. - הצהרות אופציונליות
function
: מספקים את היכולת לשלב ולעטוף תנאים לשימוש על פני כללים מרובים.
service
מכיל בלוק match
אחד או יותר עם הצהרות allow
המספקות תנאים המעניקים גישה לבקשות. משתני request
resource
זמינים לשימוש בתנאי כלל. שפת כללי האבטחה של Firebase תומכת גם בהצהרות function
.
גרסת תחביר
הצהרת syntax
מציינת את הגרסה של שפת הכללים של Firebase המשמשת לכתיבת המקור. הגרסה האחרונה של השפה היא v2
.
rules_version = '2';
service cloud.firestore {
...
}
אם לא מסופקת הצהרת rules_version
, הכללים שלך יוערכו באמצעות מנוע v1
.
שֵׁרוּת
הצהרת service
מגדירה על איזה מוצר או שירות של Firebase חלים הכללים שלך. אתה יכול לכלול רק הצהרת service
אחת לכל קובץ מקור.
Cloud Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
אחסון בענן
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
אם אתה מגדיר כללים עבור Cloud Firestore ו-Cloud Storage באמצעות Firebase CLI, תצטרך לשמור אותם בקבצים נפרדים.
התאמה
בלוק match
מכריז על דפוס path
המותאם לנתיב עבור הפעולה המבוקשת (ה- request.path
הנכנס). גוף match
חייב לכלול בלוק match
מקונן אחד או יותר, הצהרות allow
או הצהרות function
. הנתיב בבלוקים של match
מקוננת הוא יחסי לנתיב בבלוק match
האב.
תבנית path
היא שם דמוי ספרייה שעשוי לכלול משתנים או תווים כלליים. תבנית path
מאפשרת התאמות של קטעי נתיב בודדים וקטעי ריבוי נתיבים. כל משתנים הקשורים path
גלויים בטווח match
או בכל טווח מקונן שבו path
מוכרז.
התאמות מול תבנית path
עשויות להיות חלקיות או שלמות:
- התאמות חלקיות: תבנית
path
היא התאמה קידומת שלrequest.path
. - התאמות שלמות: תבנית
path
תואמת לכלrequest.path
.
כאשר מתבצעת התאמה מלאה , הכללים בתוך הבלוק מוערכים. כאשר מתבצעת התאמה חלקית , כללי match
המקוננת נבדקים כדי לראות אם path
מקונן כלשהו ישלים את ההתאמה.
הכללים בכל match
מלאה מוערכים כדי לקבוע אם להתיר את הבקשה. אם כלל התאמה כלשהו מעניק גישה, הבקשה מותרת. אם אין כלל התאמה מעניק גישה, הבקשה נדחית.
// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
// Partial match.
match /example/{singleSegment} { // `singleSegment` == 'hello'
allow write; // Write rule not evaluated.
// Complete match.
match /nested/path { // `singleSegment` visible in scope.
allow read; // Read rule is evaluated.
}
}
// Complete match.
match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
allow read; // Read rule is evaluated.
}
}
כפי שמראה הדוגמה למעלה, הצהרות path
תומכות במשתנים הבאים:
- תו כללי של מקטע יחיד: משתנה תו כללי מוכרז בנתיב על ידי גלישת משתנה בסוגריים מסולסלים:
{variable}
. משתנה זה נגיש בתוך הצהרתmatch
string
. - תו כללי רקורסיבי: התו הכללי הרקורסי, או רב-מקטע, מתאים למספר מקטעי נתיב בנתיב או מתחתיו. תו כללי זה מתאים לכל הנתיבים מתחת למיקום שהגדרת אותו. אתה יכול להכריז על זה על ידי הוספת המחרוזת
=**
בסוף משתנה הפלח שלך:{variable=**}
. משתנה זה נגיש בתוך הצהרתmatch
כאובייקטpath
.
להתיר
בלוק match
מכיל הצהרת allow
אחת או יותר. אלה הכללים האמיתיים שלך. אתה יכול להחיל כללי allow
על שיטה אחת או יותר. התנאים בהצהרת allow
חייבים להעריך כאמת כדי ש-Cloud Firestore או Cloud Storage ייענו לכל בקשה נכנסת. אתה יכול גם לכתוב הצהרות allow
ללא תנאים, לדוגמה, allow read
. אם הצהרת allow
לא כוללת תנאי, עם זאת, היא תמיד מאפשרת את הבקשה לשיטה זו.
אם מתקיימים אחד מכללי allow
לשיטה, הבקשה מותר. בנוסף, אם כלל רחב יותר מעניק גישה, כללים מעניקים גישה ומתעלמים מכללים מפורטים יותר שעלולים להגביל את הגישה.
שקול את הדוגמה הבאה, שבה כל משתמש יכול לקרוא או למחוק כל אחד מהקבצים שלו. כלל מפורט יותר מאפשר כתיבה רק אם המשתמש המבקש את הכתיבה הוא הבעלים של הקובץ והקובץ הוא PNG. משתמש יכול למחוק כל קובץ בנתיב המשנה - גם אם הם לא PNGs - מכיוון שהכלל הקודם מאפשר זאת.
service firebase.storage {
// Allow the requestor to read or delete any resource on a path under the
// user directory.
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// Allow the requestor to create or update their own images.
// When 'request.method' == 'delete' this rule and the one matching
// any path under the user directory would both match and the `delete`
// would be permitted.
match /users/{userId}/images/{imageId} {
// Whether to permit the request depends on the logical OR of all
// matched rules. This means that even if this rule did not explicitly
// allow the 'delete' the earlier rule would have.
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
שיטה
כל הצהרת allow
כוללת שיטה המעניקה גישה לבקשות נכנסות מאותה שיטה.
שיטה | סוג הבקשה |
---|---|
שיטות נוחות | |
read | כל סוג של בקשת קריאה |
write | כל סוג של בקשת כתיבה |
שיטות סטנדרטיות | |
get | קרא בקשות למסמכים או קבצים בודדים |
list | קרא בקשות לשאילתות ואוספים |
create | כתוב מסמכים או קבצים חדשים |
update | כתוב למסמכי מסד נתונים קיימים או עדכן מטא נתונים של קבצים |
delete | מחק נתונים |
לא ניתן לחפוף שיטות קריאה באותו בלוק match
או שיטות כתיבה סותרות באותה הצהרת path
.
לדוגמה, הכללים הבאים ייכשלו:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && request.auth.uid == "me";
// Overlapping write methods in the same path cause an error as well
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
פוּנקצִיָה
ככל שכללי האבטחה שלך הופכים מורכבים יותר, ייתכן שתרצה לעטוף קבוצות של תנאים בפונקציות שתוכל לעשות בהן שימוש חוזר בכל ערכת הכללים שלך. כללי אבטחה תומכים בפונקציות מותאמות אישית. התחביר של פונקציות מותאמות אישית דומה קצת ל-JavaScript, אבל פונקציות כללי אבטחה כתובות בשפה ספציפית לתחום שיש לה כמה מגבלות חשובות:
- פונקציות יכולות להכיל רק הצהרת
return
אחת. הם לא יכולים להכיל שום היגיון נוסף. לדוגמה, הם לא יכולים לבצע לולאות או להתקשר לשירותים חיצוניים. - פונקציות יכולות לגשת אוטומטית לפונקציות ומשתנים מההיקף שבו הן מוגדרות. לדוגמה, לפונקציה המוגדרת בתוך היקף
service cloud.firestore
יש גישה למשתנהresource
ולפונקציות מובנות כגוןget()
ו-exists()
. - פונקציות עשויות לקרוא לפונקציות אחרות אך לא יחזרו. עומק ערימת השיחות הכולל מוגבל ל-20.
- בגרסה
v2
של כללים, פונקציות יכולות להגדיר משתנים באמצעות מילת המפתחlet
. לפונקציות יכולות להיות עד 10 כריכות ניתנות, אך עליהן להסתיים בהצהרת return.
פונקציה מוגדרת עם מילת המפתח function
ולוקחת אפס או יותר ארגומנטים. לדוגמה, ייתכן שתרצה לשלב את שני סוגי התנאים המשמשים בדוגמאות לעיל לפונקציה אחת:
service cloud.firestore {
match /databases/{database}/documents {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}
להלן דוגמה המציגה ארגומנטים של פונקציות והקצאות תן. יש להפריד בין הצהרות מטלות בנקודה-פסיק.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
שים לב כיצד הקצאת isAdmin
אוכפת חיפוש של אוסף המנהלים. להערכה עצלנית ללא צורך בחיפושים מיותרים, נצל את האופי הקצר של &&
(AND) ו- ||
(OR) השוואות לקריאת פונקציה שנייה רק אם הוצג isAuthor
כנכון (עבור &&
השוואות) או לא נכון (עבור ||
השוואות).
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
השימוש בפונקציות בכללי האבטחה שלך הופך אותם לניתנים יותר לתחזוקה ככל שהמורכבות של הכללים שלך גדלה.
אחסון בענן
המרכיבים הבסיסיים של כלל ב-Cloud Firestore ו-Cloud Storage הם כדלקמן:
- הצהרת
service
: מצהירה על מוצר Firebase שהכללים חלים עליו. - בלוק
match
: מגדיר נתיב במסד הנתונים או בדלי האחסון שעליהם חלים הכללים. - הצהרת
allow
: מספקת תנאים למתן גישה, מובחנים לפי שיטות. השיטות הנתמכות כוללות:get
,list
,create
,update
,delete
ושיטות הנוחותread
write
. - הצהרות אופציונליות
function
: מספקים את היכולת לשלב ולעטוף תנאים לשימוש על פני כללים מרובים.
service
מכיל בלוק match
אחד או יותר עם הצהרות allow
המספקות תנאים המעניקים גישה לבקשות. משתני request
resource
זמינים לשימוש בתנאי כלל. שפת כללי האבטחה של Firebase תומכת גם בהצהרות function
.
גרסת תחביר
הצהרת syntax
מציינת את הגרסה של שפת הכללים של Firebase המשמשת לכתיבת המקור. הגרסה האחרונה של השפה היא v2
.
rules_version = '2';
service cloud.firestore {
...
}
אם לא מסופקת הצהרת rules_version
, הכללים שלך יוערכו באמצעות מנוע v1
.
שֵׁרוּת
הצהרת service
מגדירה על איזה מוצר או שירות של Firebase חלים הכללים שלך. אתה יכול לכלול רק הצהרת service
אחת לכל קובץ מקור.
Cloud Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
אחסון בענן
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
אם אתה מגדיר כללים עבור Cloud Firestore ו-Cloud Storage באמצעות Firebase CLI, תצטרך לשמור אותם בקבצים נפרדים.
התאמה
בלוק match
מכריז על דפוס path
המותאם לנתיב עבור הפעולה המבוקשת (ה- request.path
הנכנס). גוף match
חייב לכלול בלוק match
מקונן אחד או יותר, הצהרות allow
או הצהרות function
. הנתיב בבלוקים של match
מקוננת הוא יחסי לנתיב בבלוק match
האב.
תבנית path
היא שם דמוי ספרייה שעשוי לכלול משתנים או תווים כלליים. תבנית path
מאפשרת התאמות של קטעי נתיב בודדים וקטעי ריבוי נתיבים. כל משתנים הקשורים path
גלויים בטווח match
או בכל טווח מקונן שבו path
מוכרז.
התאמות מול תבנית path
עשויות להיות חלקיות או שלמות:
- התאמות חלקיות: תבנית
path
היא התאמה קידומת שלrequest.path
. - התאמות שלמות: תבנית
path
תואמת לכלrequest.path
.
כאשר מתבצעת התאמה מלאה , הכללים בתוך הבלוק מוערכים. כאשר מתבצעת התאמה חלקית , כללי match
המקוננת נבדקים כדי לראות אם path
מקונן כלשהו ישלים את ההתאמה.
הכללים בכל match
מלאה מוערכים כדי לקבוע אם להתיר את הבקשה. אם כלל התאמה כלשהו מעניק גישה, הבקשה מותרת. אם אין כלל התאמה מעניק גישה, הבקשה נדחית.
// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
// Partial match.
match /example/{singleSegment} { // `singleSegment` == 'hello'
allow write; // Write rule not evaluated.
// Complete match.
match /nested/path { // `singleSegment` visible in scope.
allow read; // Read rule is evaluated.
}
}
// Complete match.
match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
allow read; // Read rule is evaluated.
}
}
כפי שמראה הדוגמה למעלה, הצהרות path
תומכות במשתנים הבאים:
- תו כללי של מקטע יחיד: משתנה תו כללי מוכרז בנתיב על ידי גלישת משתנה בסוגריים מסולסלים:
{variable}
. משתנה זה נגיש בתוך הצהרתmatch
string
. - תו כללי רקורסיבי: התו הכללי הרקורסי, או רב-מקטע, מתאים למספר מקטעי נתיב בנתיב או מתחתיו. תו כללי זה מתאים לכל הנתיבים מתחת למיקום שהגדרת אותו. אתה יכול להכריז על זה על ידי הוספת המחרוזת
=**
בסוף משתנה הפלח שלך:{variable=**}
. משתנה זה נגיש בתוך הצהרתmatch
כאובייקטpath
.
להתיר
בלוק match
מכיל הצהרת allow
אחת או יותר. אלה הכללים האמיתיים שלך. אתה יכול להחיל כללי allow
על שיטה אחת או יותר. התנאים בהצהרת allow
חייבים להעריך כאמת כדי ש-Cloud Firestore או Cloud Storage ייענו לכל בקשה נכנסת. אתה יכול גם לכתוב הצהרות allow
ללא תנאים, לדוגמה, allow read
. אם הצהרת allow
לא כוללת תנאי, עם זאת, היא תמיד מאפשרת את הבקשה לשיטה זו.
אם מתקיימים אחד מכללי allow
לשיטה, הבקשה מותר. בנוסף, אם כלל רחב יותר מעניק גישה, כללים מעניקים גישה ומתעלמים מכללים מפורטים יותר שעלולים להגביל את הגישה.
שקול את הדוגמה הבאה, שבה כל משתמש יכול לקרוא או למחוק כל אחד מהקבצים שלו. כלל מפורט יותר מאפשר כתיבה רק אם המשתמש המבקש את הכתיבה הוא הבעלים של הקובץ והקובץ הוא PNG. משתמש יכול למחוק כל קובץ בנתיב המשנה - גם אם הם לא PNGs - מכיוון שהכלל הקודם מאפשר זאת.
service firebase.storage {
// Allow the requestor to read or delete any resource on a path under the
// user directory.
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// Allow the requestor to create or update their own images.
// When 'request.method' == 'delete' this rule and the one matching
// any path under the user directory would both match and the `delete`
// would be permitted.
match /users/{userId}/images/{imageId} {
// Whether to permit the request depends on the logical OR of all
// matched rules. This means that even if this rule did not explicitly
// allow the 'delete' the earlier rule would have.
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
שיטה
כל הצהרת allow
כוללת שיטה המעניקה גישה לבקשות נכנסות מאותה שיטה.
שיטה | סוג הבקשה |
---|---|
שיטות נוחות | |
read | כל סוג של בקשת קריאה |
write | כל סוג של בקשת כתיבה |
שיטות סטנדרטיות | |
get | קרא בקשות למסמכים או קבצים בודדים |
list | קרא בקשות לשאילתות ואוספים |
create | כתוב מסמכים או קבצים חדשים |
update | כתוב למסמכי מסד נתונים קיימים או עדכן מטא נתונים של קבצים |
delete | מחק נתונים |
לא ניתן לחפוף שיטות קריאה באותו בלוק match
או שיטות כתיבה סותרות באותה הצהרת path
.
לדוגמה, הכללים הבאים ייכשלו:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && request.auth.uid == "me";
// Overlapping write methods in the same path cause an error as well
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
פוּנקצִיָה
ככל שכללי האבטחה שלך הופכים מורכבים יותר, ייתכן שתרצה לעטוף קבוצות של תנאים בפונקציות שתוכל לעשות בהן שימוש חוזר בכל ערכת הכללים שלך. כללי אבטחה תומכים בפונקציות מותאמות אישית. התחביר של פונקציות מותאמות אישית דומה קצת ל-JavaScript, אבל פונקציות כללי אבטחה כתובות בשפה ספציפית לתחום שיש לה כמה מגבלות חשובות:
- פונקציות יכולות להכיל רק הצהרת
return
אחת. הם לא יכולים להכיל שום היגיון נוסף. לדוגמה, הם לא יכולים לבצע לולאות או להתקשר לשירותים חיצוניים. - פונקציות יכולות לגשת אוטומטית לפונקציות ומשתנים מההיקף שבו הן מוגדרות. לדוגמה, לפונקציה המוגדרת בתוך היקף
service cloud.firestore
יש גישה למשתנהresource
ולפונקציות מובנות כגוןget()
ו-exists()
. - פונקציות עשויות לקרוא לפונקציות אחרות אך לא יחזרו. עומק ערימת השיחות הכולל מוגבל ל-20.
- בגרסה
v2
של כללים, פונקציות יכולות להגדיר משתנים באמצעות מילת המפתחlet
. לפונקציות יכולות להיות עד 10 כריכות ניתנות, אך עליהן להסתיים בהצהרת return.
פונקציה מוגדרת עם מילת המפתח function
ולוקחת אפס או יותר ארגומנטים. לדוגמה, ייתכן שתרצה לשלב את שני סוגי התנאים המשמשים בדוגמאות לעיל לפונקציה אחת:
service cloud.firestore {
match /databases/{database}/documents {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}
להלן דוגמה המציגה ארגומנטים של פונקציות והקצאות תן. יש להפריד בין הצהרות מטלות בנקודה-פסיק.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
שים לב כיצד הקצאת isAdmin
אוכפת חיפוש של אוסף המנהלים. להערכה עצלנית ללא צורך בחיפושים מיותרים, נצל את האופי הקצר של &&
(AND) ו- ||
(OR) השוואות לקריאת פונקציה שנייה רק אם הוצג isAuthor
כנכון (עבור &&
השוואות) או לא נכון (עבור ||
השוואות).
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
השימוש בפונקציות בכללי האבטחה שלך הופך אותם לניתנים יותר לתחזוקה ככל שהמורכבות של הכללים שלך גדלה.
מסד נתונים בזמן אמת
כפי שפורט לעיל, כללי מסד נתונים בזמן אמת כוללים שלושה אלמנטים בסיסיים: מיקום מסד הנתונים כמראה של מבנה ה-JSON של מסד הנתונים, סוג הבקשה והתנאי המעניק גישה.
מיקום מסד הנתונים
מבנה הכללים שלך צריך להיות בהתאם למבנה הנתונים ששמרת במסד הנתונים שלך. לדוגמה, באפליקציית צ'אט עם רשימת הודעות, ייתכן שיש לך נתונים שנראים כך:
{
"messages": {
"message0": {
"content": "Hello",
"timestamp": 1405704370369
},
"message1": {
"content": "Goodbye",
"timestamp": 1405704395231
},
...
}
}
הכללים שלך צריכים לשקף את המבנה הזה. לדוגמה:
{
"rules": {
"messages": {
"$message": {
// only messages from the last ten minutes can be read
".read": "data.child('timestamp').val() > (now - 600000)",
// new messages must have a string content and a number timestamp
".validate": "newData.hasChildren(['content', 'timestamp']) &&
newData.child('content').isString() &&
newData.child('timestamp').isNumber()"
}
}
}
}
כפי שמראה הדוגמה למעלה, כללי מסד נתונים בזמן אמת תומכים במשתנה $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 }
}
}
}
שיטה
במסד נתונים בזמן אמת, ישנם שלושה סוגים של כללים. שניים מסוגי כללים אלה - read
write
- חלים על השיטה של בקשה נכנסת. סוג כלל validate
אוכף מבני נתונים ומאמת את הפורמט והתוכן של הנתונים. כללים מפעילים כללי .validate
לאחר וידוא שכלל .write
מעניק גישה.
סוגי כללים | |
---|---|
.לקרוא | מתאר אם ומתי מותר לקרוא נתונים על ידי משתמשים. |
.לִכתוֹב | מתאר אם ומתי מותר לכתוב נתונים. |
.לְאַמֵת | מגדיר כיצד ייראה ערך בפורמט נכון, האם יש לו תכונות צאצא וסוג הנתונים. |
כברירת מחדל, אם אין כלל המאפשר זאת, הגישה בנתיב נדחית.
תנאי בנייה
Cloud Firestore
תנאי הוא ביטוי בוליאני שקובע אם יש לאפשר או לדחות פעולה מסוימת. משתני request
resource
מספקים הקשר לתנאים אלה.
משתנה request
משתנה request
כולל את השדות הבאים ומידע מתאים:
request.auth
JSON Web Token (JWT) המכיל אישורי אימות מאימות Firebase. auth
token מכיל קבוצה של תביעות סטנדרטיות וכל תביעות מותאמות אישית שאתה יוצר באמצעות אימות Firebase. למידע נוסף על כללי אבטחה ואימות של Firebase .
request.method
ה- request.method
עשויה להיות כל אחת מהשיטות הסטנדרטיות או שיטה מותאמת אישית. שיטות הנוחות read
write
קיימות גם כדי לפשט את כללי הכתיבה החלים על כל השיטות הסטנדרטיות לקריאה בלבד או על כל שיטות הכתיבה בלבד, בהתאמה.
request.params
ה- request.params
כוללים כל מידע שאינו קשור ספציפית ל- request.resource
שעשוי להיות שימושי להערכה. בפועל, מפה זו צריכה להיות ריקה עבור כל השיטות הסטנדרטיות, ועליה להכיל נתונים שאינם משאבים עבור שיטות מותאמות אישית. על השירותים להקפיד לא לשנות שם או לשנות את סוג כל אחד מהמפתחות והערכים המוצגים כפרמים.
request.path
ה- request.path
הוא הנתיב עבור resource
היעד. הדרך היא יחסית לשירות. קטעי נתיב המכילים תווים בטוחים שאינם כתובות אתרים כגון /
מקודדים ב-url.
משתנה resource
resource
הוא הערך הנוכחי בתוך השירות המיוצג כמפה של צמדי מפתח-ערך. הפניה של resource
בתוך תנאי תגרום לקריאה אחת לכל היותר של הערך מהשירות. חיפוש זה ייחשב כנגד כל מכסה הקשורה לשירות עבור המשאב. עבור בקשות get
, resource
ייחשב רק למכסה בעת דחייה.
מפעילים וקדימות מפעילים
השתמש בטבלה שלהלן כהתייחסות למפעילים ובעדיפותם המתאימה בכללים עבור Cloud Firestore ו-Cloud Storage.
בהינתן ביטויים שרירותיים a
ו- b
, שדה f
, ואינדקס i
.
מַפעִיל | תיאור | אסוציאטיביות |
---|---|---|
a[i] a() af | אינדקס, שיחה, גישה לשדה | משמאל לימין | !a -a | שלילה לא נורית | מימין לשמאל |
a/ba%ba*b | אופרטורים כפולים | משמאל לימין |
a+b ab | מפעילי תוספים | משמאל לימין |
a>ba>=ba | מפעילים יחסיים | משמאל לימין |
a in b | קיום ברשימה או במפה | משמאל לימין |
a is type | השוואת סוגים, כאשר type יכול להיות bool, int, float, number, מחרוזת, רשימה, מפה, חותמת זמן, משך, נתיב או latlng | משמאל לימין |
a==ba!=b | מפעילי השוואה | משמאל לימין | a && b | AND מותנה | משמאל לימין |
a || b | OR מותנה | משמאל לימין |
a ? true_value : false_value | ביטוי טרנרי | משמאל לימין |
אחסון בענן
תנאי הוא ביטוי בוליאני שקובע אם יש לאפשר או לדחות פעולה מסוימת. משתני request
resource
מספקים הקשר לתנאים אלה.
משתנה request
משתנה request
כולל את השדות הבאים ומידע מתאים:
request.auth
JSON Web Token (JWT) המכיל אישורי אימות מאימות Firebase. auth
token מכיל קבוצה של תביעות סטנדרטיות וכל תביעות מותאמות אישית שאתה יוצר באמצעות אימות Firebase. למידע נוסף על כללי אבטחה ואימות של Firebase .
request.method
ה- request.method
עשויה להיות כל אחת מהשיטות הסטנדרטיות או שיטה מותאמת אישית. שיטות הנוחות read
write
קיימות גם כדי לפשט את כללי הכתיבה החלים על כל השיטות הסטנדרטיות לקריאה בלבד או על כל שיטות הכתיבה בלבד, בהתאמה.
request.params
ה- request.params
כוללים כל מידע שאינו קשור ספציפית ל- request.resource
שעשוי להיות שימושי להערכה. בפועל, מפה זו צריכה להיות ריקה עבור כל השיטות הסטנדרטיות, ועליה להכיל נתונים שאינם משאבים עבור שיטות מותאמות אישית. על השירותים להקפיד לא לשנות שם או לשנות את סוג כל אחד מהמפתחות והערכים המוצגים כפרמים.
request.path
ה- request.path
הוא הנתיב עבור resource
היעד. הדרך היא יחסית לשירות. קטעי נתיב המכילים תווים בטוחים שאינם כתובות אתרים כגון /
מקודדים ב-url.
משתנה resource
resource
הוא הערך הנוכחי בתוך השירות המיוצג כמפה של צמדי מפתח-ערך. הפניה של resource
בתוך תנאי תגרום לקריאה אחת לכל היותר של הערך מהשירות. חיפוש זה ייחשב כנגד כל מכסה הקשורה לשירות עבור המשאב. עבור בקשות get
, resource
ייחשב רק למכסה בעת דחייה.
מפעילים וקדימות מפעילים
השתמש בטבלה שלהלן כהתייחסות למפעילים ובעדיפותם המתאימה בכללים עבור Cloud Firestore ו-Cloud Storage.
בהינתן ביטויים שרירותיים a
ו- b
, שדה f
, ואינדקס i
.
מַפעִיל | תיאור | אסוציאטיביות |
---|---|---|
a[i] a() af | אינדקס, שיחה, גישה לשדה | משמאל לימין | !a -a | שלילה לא נורית | מימין לשמאל |
a/ba%ba*b | אופרטורים כפולים | משמאל לימין |
a+b ab | מפעילי תוספים | משמאל לימין |
a>ba>=ba | מפעילים יחסיים | משמאל לימין |
a in b | קיום ברשימה או במפה | משמאל לימין |
a is type | השוואת סוגים, כאשר type יכול להיות bool, int, float, number, מחרוזת, רשימה, מפה, חותמת זמן, משך, נתיב או latlng | משמאל לימין |
a==ba!=b | מפעילי השוואה | משמאל לימין | a && b | AND מותנה | משמאל לימין |
a || b | OR מותנה | משמאל לימין |
a ? true_value : false_value | ביטוי טרנרי | משמאל לימין |
מסד נתונים בזמן אמת
תנאי הוא ביטוי בוליאני שקובע אם יש לאפשר או לדחות פעולה מסוימת. אתה יכול להגדיר את התנאים האלה בכללי מסד נתונים בזמן אמת בדרכים הבאות.
משתנים מוגדרים מראש
ישנם מספר משתנים מועילים ומוגדרים מראש שניתן לגשת אליהם בתוך הגדרת כלל. להלן סיכום קצר של כל אחד מהם:
משתנים מוגדרים מראש | |
---|---|
עַכשָׁיו | הזמן הנוכחי באלפיות שניות מאז עידן לינוקס. זה עובד טוב במיוחד עבור אימות חותמות זמן שנוצרו עם ה-SDK של firebase.database.ServerValue.TIMESTAMP. |
שורש | RuleDataSnapshot המייצג את נתיב הבסיס במסד הנתונים של Firebase כפי שהוא קיים לפני ניסיון הפעולה. |
מידע חדש | RuleDataSnapshot המייצג את הנתונים כפי שהם יהיו קיימים לאחר ניסיון הפעולה. הוא כולל את הנתונים החדשים הנכתבים ואת הנתונים הקיימים. |
נתונים | RuleDataSnapshot המייצג את הנתונים כפי שהיו קיימים לפני ניסיון הפעולה. |
משתני $ | נתיב תווים כלליים המשמשים לייצוג מזהים ומפתחות צאצאים דינמיים. |
אישור | מייצג את מטען האסימון של משתמש מאומת. |
ניתן להשתמש במשתנים אלה בכל מקום בכללים שלך. לדוגמה, כללי האבטחה שלהלן מבטיחים שהנתונים הנכתבים לצומת /foo/
חייבים להיות מחרוזת בת פחות מ-100 תווים:
{ "rules": { "foo": { // /foo is readable by the world ".read": true, // /foo is writable by the world ".write": true, // data written to /foo must be a string less than 100 characters ".validate": "newData.isString() && newData.val().length < 100" } } }
כללים מבוססי נתונים
ניתן להשתמש בכל הנתונים במסד הנתונים שלך בכללים שלך. באמצעות המשתנים המוגדרים מראש root
, data
ו- newData
, אתה יכול לגשת לכל נתיב כפי שהיה קיים לפני או אחרי אירוע כתיבה.
שקול את הדוגמה הזו, המאפשרת פעולות כתיבה כל עוד הערך של הצומת /allow_writes/
true
, לצומת האב אין ערכת דגל readOnly
, ויש ילד בשם foo
בנתונים החדשים שנכתבו:
".write": "root.child('allow_writes').val() === true && !data.parent().child('readOnly').exists() && newData.child('foo').exists()"
כללים מבוססי שאילתה
למרות שאינך יכול להשתמש בכללים כמסננים, אתה יכול להגביל את הגישה לקבוצות משנה של נתונים על ידי שימוש בפרמטרי שאילתה בכללים שלך. השתמש query.
ביטויים בכללים שלך כדי להעניק גישת קריאה או כתיבה על סמך פרמטרי שאילתה.
לדוגמה, הכלל הבא המבוסס על שאילתות משתמש בכללי אבטחה מבוססי משתמשים ובכללים מבוססי שאילתות כדי להגביל את הגישה לנתונים באוסף baskets
רק לסל הקניות שבבעלות המשתמש הפעיל:
"baskets": {
".read": "auth.uid !== null &&
query.orderByChild === 'owner' &&
query.equalTo === auth.uid" // restrict basket access to owner of basket
}
השאילתה הבאה, הכוללת את פרמטרי השאילתה בכלל, תצליח:
db.ref("baskets").orderByChild("owner")
.equalTo(auth.currentUser.uid)
.on("value", cb) // Would succeed
עם זאת, שאילתות שאינן כוללות את הפרמטרים בכלל ייכשלו עם שגיאה PermissionDenied
:
db.ref("baskets").on("value", cb) // Would fail with PermissionDenied
אתה יכול גם להשתמש בכללים מבוססי שאילתה כדי להגביל את כמות הנתונים שלקוח מוריד באמצעות פעולות קריאה.
לדוגמה, הכלל הבא מגביל את גישת הקריאה רק ל-1000 התוצאות הראשונות של שאילתה, לפי סדר עדיפות:
messages: {
".read": "query.orderByKey &&
query.limitToFirst <= 1000"
}
// Example queries:
db.ref("messages").on("value", cb) // Would fail with PermissionDenied
db.ref("messages").limitToFirst(1000)
.on("value", cb) // Would succeed (default order by key)
query.
ביטויים זמינים בכללי האבטחה של מסד נתונים בזמן אמת.
ביטויי כלל מבוססי שאילתה | ||
---|---|---|
ביטוי | סוּג | תיאור |
query.orderByKey query.orderByPriority query.orderByValue | בוליאני | נכון עבור שאילתות מסודרות לפי מפתח, עדיפות או ערך. שקר אחרת. |
query.orderByChild | חוּט ריק | השתמש במחרוזת כדי לייצג את הנתיב היחסי לצומת צאצא. לדוגמה, query.orderByChild === "address/zip" . אם השאילתה לא מסודרת על ידי צומת צאצא, ערך זה הוא null. |
query.startAt query.endAt query.equalTo | חוּט מספר בוליאני ריק | מאחזר את הגבולות של השאילתה המבצעת, או מחזיר null אם אין קבוצה מוגבלת. |
query.limitToFirst query.limitToLast | מספר ריק | מאחזר את המגבלה על השאילתה המבצעת, או מחזיר null אם לא הוגדרה מגבלה. |
מפעילים
חוקי מסד נתונים בזמן אמת תומכים במספר אופרטורים שבהם אתה יכול להשתמש כדי לשלב משתנים בהצהרת התנאי. ראה את הרשימה המלאה של מפעילים בתיעוד ההפניה .
יצירת תנאים
התנאים האמיתיים שלך ישתנו בהתאם לגישה שאתה רוצה להעניק. כללים מציעים בכוונה מידה עצומה של גמישות, כך שכללי האפליקציה שלך יכולים בסופו של דבר להיות פשוטים או מורכבים כפי שאתה צריך שהם יהיו.
לקבלת הנחיות ליצירת כללים פשוטים ומוכנים לייצור, ראה כללי אבטחה בסיסיים .