Check out what’s new from Firebase@ Google I/O 2021, and join our alpha program for early access to the new Remote Config personalization feature. Learn more

שפת כללי האבטחה

כללי האבטחה של Firebase ממנפים שפות גמישות, חזקות ומותאמות אישית התומכות במגוון רחב של מורכבות ופירוט. אתה יכול להפוך את הכללים שלך לספציפיים או כלליים כמו הגיוני לאפליקציה שלך. כללי מסד נתונים בזמן אמת משתמשים בתחביר שנראה כמו JavaScript במבנה JSON. כללי Cloud Firestore ו- Cloud Storage משתמשים בשפה המבוססת על שפת Common Expression (CEL) , הבונה על CEL עם match allow הצהרות התומכות בגישה הניתנת בתנאי.

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

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

מבנה בסיסי

ענן 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 משמשים אימות משני להענקת גישה על בסיס נתונים נכנסים או קיימים.
  • תנאי: התנאי שמתיר בקשה אם היא מעריכה כנכונה.

בונה שלטון

ענן Firestore

המרכיבים הבסיסיים של כלל בענן 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 הצהרת rules_version , הכללים שלך יוערכו באמצעות מנוע v1 .

שֵׁרוּת

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

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

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

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

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 כריכות תן, אך עליהן להסתיים בהצהרת החזרה.

פונקציה מוגדרת בעזרת מילת המפתח של 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);
}

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

אחסון בענן

המרכיבים הבסיסיים של כלל בענן 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 הצהרת rules_version , הכללים שלך יוערכו באמצעות מנוע v1 .

שֵׁרוּת

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

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

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

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

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 כריכות תן, אך עליהן להסתיים בהצהרת החזרה.

פונקציה מוגדרת בעזרת מילת המפתח של 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 הכלל המקנה גישה.

סוגי הכללים
.לקרוא מתאר אם ומתי משתמשים יכולים לקרוא נתונים.
.לִכתוֹב מתאר אם ומתי מותר לכתוב נתונים.
.לְאַמֵת מגדיר כיצד ייראה ערך מעוצב כהלכה, האם יש לו מאפייני ילד וסוג הנתונים.

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

תנאי בנייה

ענן Firestore

תנאי הוא ביטוי בוליאני הקובע אם יש לאפשר או לדחות פעולה מסוימת. משתני request resource מספקים הקשר לתנאים אלה.

משתנה request

משתנה request כולל את השדות הבאים ומידע מתאים:

request.auth

אסימון אינטרנט של JSON (JWT) המכיל אישורי אימות מאימות Firebase. אסימון auth מכיל קבוצה של תביעות סטנדרטיות וכל תביעות מותאמות אישית שתיצור באמצעות אימות Firebase. למידע נוסף על כללי אבטחה ואימות של Firebase .

request.method

request.method .method עשויה להיות כל אחת מהשיטות הסטנדרטיות או שיטה מותאמת אישית. שיטות הנוחות read write קיימות גם כדי לפשט כללי כתיבה החלים על כל השיטות הסטנדרטיות לקריאה בלבד או על כל הכתיבה בלבד בהתאמה.

request.params

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

request.path

המסלול request.path הוא הנתיב עבור resource היעד. הנתיב הוא יחסית לשירות. פלחי נתיב המכילים תווים שאינם בטוחים לכתובת אתר כגון / מקודדים לכתובת אתר.

משתנה resource

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

מפעילים וקדימות מפעיל

השתמש בטבלה שלהלן כהפניה למפעילים ולקדימות המתאימה להם בכללים עבור Cloud Firestore ו- Cloud Storage.

ניתן ביטויים שרירותיים a ו- b , שדה f , ומדד i .

מַפעִיל תיאור אסוציאטיביות
a[i] a() af אינדקס, שיחה, גישה לשטח משמאל לימין
!a -a שלילה unary מימין לשמאל
a/ba%ba*b מפעילים מכפלים משמאל לימין
a+b ab מפעילים תוספים משמאל לימין
a>ba>=ba מפעילים יחסיים משמאל לימין
a in b קיום ברשימה או במפה משמאל לימין
a is type השוואת סוגים, כאשר type יכול להיות bool, int, float, מספר, מחרוזת, רשימה, מפה, חותמת זמן, משך, נתיב או latlng משמאל לימין
a==ba!=b מפעילי השוואה משמאל לימין
a && b מותנה AND משמאל לימין
a || b OR מותנה משמאל לימין
a ? true_value : false_value ביטוי טרני משמאל לימין

אחסון בענן

תנאי הוא ביטוי בוליאני הקובע אם יש לאפשר או לדחות פעולה מסוימת. משתני request resource מספקים הקשר לתנאים אלה.

משתנה request

משתנה request כולל את השדות הבאים ומידע מתאים:

request.auth

אסימון אינטרנט של JSON (JWT) המכיל אישורי אימות מאימות Firebase. אסימון auth מכיל קבוצה של תביעות סטנדרטיות וכל תביעות מותאמות אישית שתיצור באמצעות אימות Firebase. למידע נוסף על כללי אבטחה של Firebase ואימות .

request.method

request.method .method עשויה להיות כל אחת מהשיטות הסטנדרטיות או שיטה מותאמת אישית. שיטות הנוחות read write קיימות גם כדי לפשט כללי כתיבה החלים על כל השיטות הסטנדרטיות לקריאה בלבד או על כל הכתיבה בלבד בהתאמה.

request.params

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

request.path

המסלול request.path הוא הנתיב עבור resource היעד. הנתיב הוא יחסית לשירות. פלחי נתיב המכילים תווים שאינם בטוחים לכתובת אתר כגון / מקודדים לכתובת אתר.

משתנה resource

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

מפעילים וקדימות מפעיל

השתמש בטבלה שלהלן כהפניה למפעילים ולקדימות המתאימה להם בכללים עבור Cloud Firestore ו- Cloud Storage.

ניתן ביטויים שרירותיים a ו- b , שדה f , ומדד i .

מַפעִיל תיאור אסוציאטיביות
a[i] a() af אינדקס, שיחה, גישה לשטח משמאל לימין
!a -a שלילה unary מימין לשמאל
a/ba%ba*b מפעילים מכפלים משמאל לימין
a+b ab מפעילים תוספים משמאל לימין
a>ba>=ba מפעילים יחסיים משמאל לימין
a in b קיום ברשימה או במפה משמאל לימין
a is type השוואת סוגים, כאשר type יכול להיות bool, int, float, מספר, מחרוזת, רשימה, מפה, חותמת זמן, משך, נתיב או latlng משמאל לימין
a==ba!=b מפעילי השוואה משמאל לימין
a && b מותנה AND משמאל לימין
a || b OR מותנה משמאל לימין
a ? true_value : false_value ביטוי טרני משמאל לימין

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

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

משתנים שהוגדרו מראש

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

משתנים מוגדרים מראש
עַכשָׁיו הזמן הנוכחי באלפיות השנייה מאז תקופת לינוקס. זה עובד טוב במיוחד לאימות חותמות זמן שנוצרו באמצעות ה- firebase.database.ServerValue.TIMESTAMP של ה- SDK.
שורש RuleDataSnapshot המייצג את נתיב הבסיס במסד הנתונים של Firebase כפי שהוא קיים לפני ניסיון הפעולה.
מידע חדש RuleDataSnapshot המייצג את הנתונים כפי שהם היו קיימים לאחר ניסיון הפעולה. הוא כולל את הנתונים החדשים שנכתבים ואת הנתונים הקיימים.
נתונים RuleDataSnapshot המייצג את הנתונים כפי שהיו לפני ניסיון הפעולה.
משתנים $ שביל תווים כלליים המשמש לייצוג מזהים ומפתחות ילדים דינמיים.
אימות מייצג מטען סמלי של משתמש מאומת.

ניתן להשתמש במשתנים אלה בכל מקום בכללים שלך. לדוגמא, כללי האבטחה שלהלן מבטיחים כי נתונים שנכתבים אל /foo/ node צריכים להיות מחרוזת של פחות מ -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"
    }
  }
}

כללים מבוססי נתונים

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

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

ביטויים של כלל מבוסס שאילתות
ביטוי סוּג תיאור
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 אם לא מוגדרת מגבלה.

מפעילים

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

יצירת תנאים

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

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