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

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

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

הצהרת שירות ומאגר מידע

כללי האבטחה של Cloud Firestore מתחילים תמיד בהצהרה הבאה:

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

הצהרת service cloud.firestore מקיפה את הכללים ל-Cloud Firestore, ומונעת התנגשויות בין כללי האבטחה של Cloud Firestore לבין כללים עבור מוצרים אחרים כגון 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 and 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 (לא מותר)
מספר מקסימלי של ביטויים שהוערך לכל בקשה 1,000
גודל מקסימלי של ערכת כללים על ערכות הכללים לציית לשתי מגבלות גודל:
  • מגבלה של 256 KB על גודל מקור הטקסט של ערכת הכללים שפורסם ממסוף Firebase או מה-CLI באמצעות firebase deploy .
  • מגבלה של 250 קילו-בייט על גודל ערכת הכללים הקומפילית שנוצרת כאשר Firebase מעבד את המקור והופך אותו לפעיל בקצה האחורי.

הצעדים הבאים