מבנה של כללי אבטחה ב-Cloud Firestore

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

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

הצהרה על שירותים ומסדי נתונים

Cloud Firestore Security Rules תמיד מתחיל בהצהרה הבאה:

service cloud.firestore {
  match /databases/{database}/documents {
    // ...
  }
}

ההצהרה service cloud.firestore מגבילה את ההיקף של הכללים ל-Cloud Firestore, כדי למנוע התנגשויות בין Cloud Firestore Security Rules לבין כללים של מוצרים אחרים, כמו Cloud Storage.

ההצהרה match /databases/{database}/documents מציינת שהכללים צריכים להתאים לכל מסד נתונים של Cloud Firestore בפרויקט. נכון לעכשיו, לכל פרויקט יש רק מסד נתונים אחד בשם (default).

כללי קריאה/כתיבה בסיסיים

כללים בסיסיים מורכבים מהצהרה match שמציינת את נתיב המסמך, ומותר להשתמש בביטוי allow המפרט את קריאת הנתונים שצוינו:

service cloud.firestore {
  match /databases/{database}/documents {

    // Match any document in the 'cities' collection
    match /cities/{city} {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

כל הצהרות ההתאמה צריכות להפנות למסמכים, לא לאוספים. הצהרת ההתאמה יכולה להפנות למסמך ספציפי, למשל ב-match /cities/SF, או להשתמש בתווים כלליים לחיפוש כדי להצביע על כל מסמך בנתיב שצוין, כמו ב-match /cities/{city}.

בדוגמה שלמעלה, הצהרת ההתאמה משתמשת בתחביר של התו הכללי לחיפוש {city}. המשמעות היא שהכלל חל על כל מסמך באוסף cities, כמו /cities/SF או /cities/NYC. כשהביטויים allow במשפט ההתאמה ייבדקו, המשתנה city יתורגם לשם של מסמך העיר, למשל SF או NYC.

פעולות מפורטות

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

אפשר לפצל כלל read ל-get ול-list, ואפשר לפצל כלל write ל-create, ל-update ול-delete:

service cloud.firestore {
  match /databases/{database}/documents {
    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if <condition>;

      // Applies to queries and collection read requests
      allow list: if <condition>;
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if <condition>;

      // Applies to writes to existing documents
      allow update: if <condition>;

      // Applies to delete operations
      allow delete: if <condition>;
    }
  }
}

נתונים היררכיים

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

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

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      allow read, write: if <condition>;

        // Explicitly define rules for the 'landmarks' subcollection
        match /landmarks/{landmark} {
          allow read, write: if <condition>;
        }
    }
  }
}

כשמציבים הצהרות match בתוך הצהרה, הנתיב של ההצהרה הפנימית match תמיד יחסי לנתיב של ההצהרה החיצונית match. לכן, כללי המדיניות הבאים זהים:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}
service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city}/landmarks/{landmark} {
      allow read, write: if <condition>;
    }
  }
}

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

כדי להחיל כללים על היררכיה עמוקה באופן שרירותי, צריך להשתמש בתחביר של התו הכללי לחיפוש רקורסיבי, {name=**}. לדוגמה:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

כשמשתמשים בתחביר של התווים הכלליים לחיפוש רקורסיבי, משתנה התו הכללי לחיפוש יכיל את קטע הנתיב התואם במלואו, גם אם המסמך ממוקם באוסף משנה בתוך אוסף משנה. לדוגמה, הכללים שמפורטים למעלה יתאימו למסמך שנמצא בכתובת /cities/SF/landmarks/coit_tower, והערך של המשתנה document יהיה SF/landmarks/coit_tower.

עם זאת, חשוב לזכור שההתנהגות של תווים כלליים רפלקסיביים תלויה בגרסה של הכללים.

גרסה 1

כללי האבטחה משתמשים בגרסה 1 כברירת מחדל. בגרסה 1, תווים כלליים רפלקסיביים תואמים לפריט נתיב אחד או יותר. הם לא תואמים לנתיב ריק, לכן match /cities/{city}/{document=**} מתאים למסמכים באוספי משנה אבל לא באוסף cities, ואילו match /cities/{document=**} תואם לשני המסמכים באוסף cities ובאוספי המשנה.

תווים כלליים רפלקסיביים חייבים להופיע בסוף משפט התאמה.

גרסה 2

בגרסה 2 של כללי האבטחה, תווים כלליים לחיפוש רקורסיביים תואמים לאפס פריטי נתיב או יותר. match/cities/{city}/{document=**} תואמת למסמכים בכל אוספי המשנה וגם למסמכים באוסף cities.

חייבים להצטרף לגרסה 2 על ידי הוספת rules_version = '2'; בראש כללי האבטחה:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{city}/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

אפשר להוסיף לכל הצהרת התאמה תו כללי לחיפוש רקורסיבי אחד לכל היותר, אבל בגרסה 2 אפשר להציב את התו הכללי לחיפוש בכל מקום בהצהרת ההתאמה. לדוגמה:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the songs collection group
    match /{path=**}/songs/{song} {
      allow read, write: if <condition>;
    }
  }
}

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

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

יכול להיות שמסמך יתאים ליותר מטענת match אחת. במקרה שבו כמה ביטויים של allow תואמים לבקשה, הגישה מותרת אם אחד מהתנאים הוא true:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the 'cities' collection.
    match /cities/{city} {
      allow read, write: if false;
    }

    // Matches any document in the 'cities' collection or subcollections.
    match /cities/{document=**} {
      allow read, write: if true;
    }
  }
}

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

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

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

הגבלה פרטים
מספר מקסימלי של exists(), get() ו-getAfter() שיחות לכל בקשה
  • 10 לבקשות למסמך יחיד ובקשות שאילתה.
  • 20 לקריאות של מסמכים מרובים, לעסקאות ולכתיבה באצווה. המגבלה הקודמת של 10 חלה גם על כל פעולה.

    לדוגמה, נניח שיצרתם בקשת כתיבה באצווה עם 3 פעולות כתיבה, ושכללי האבטחה שלכם משתמשים ב-2 קריאות גישה למסמך כדי לאמת כל פעולת כתיבה. במקרה כזה, כל כתיבה משתמשת ב-2 מתוך 10 קריאות הגישה שלה, ובקשת הכתיבה באצווה משתמשת ב-6 מתוך 20 קריאות הגישה שלה.

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

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

העומק המקסימלי של דף חשבון match בתצוגת עץ 10
אורך נתיב מקסימלי, במקטעי נתיב, מותר בתוך קבוצה של הצהרות match מקוננות 100
המספר המקסימלי של משתני תיעוד נתיב שמותר להשתמש בהם בתוך קבוצה של משפטי match בתצוגת עץ 20
עומק קריאה מקסימלי של פונקציה 20
מספר הארגומנטים המקסימלי של פונקציה 7
המספר המקסימלי של קישורי משתני let לכל פונקציה 10
המספר המקסימלי של הפעלות של פונקציות רקורסיביות או מחזוריות 0 &lpar;לא אפשרי&rpar;
המספר המקסימלי של ביטויים שנבדקים לכל בקשה 1,000
הגודל המקסימלי של קבוצת כללים קבוצות כללים צריכות לציית לשתי מגבלות גודל:
  • מגבלה של 256KB על גודל מקור הטקסט בקבוצת הכללים שפורסמה ממסוף Firebase או מ-CLI באמצעות firebase deploy.
  • מגבלה של 250KB על גודל קבוצת הכללים המורכבת שמתרחשת כשמערכת Firebase מעבדת את המקור ומופעלת בקצה העורפי.

השלבים הבאים