היכרות עם התחביר העיקרי של כללי האבטחה של Firebase לשפה של Cloud Storage

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

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

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

Firebase Security Rules של Cloud Storage תמיד מתחיל בהצהרה הבאה:

service firebase.storage {
    // ...
}

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

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

כללים בסיסיים מורכבים מהצהרה match שמזהה את Cloud Storage קטגוריות, הצהרת התאמה שמציינת שם קובץ וביטוי allow מותר לציין פרטים בזמן קריאת הנתונים שצוינו. allow ביטויים לציין את שיטות הגישה (למשל: קריאה, כתיבה) מעורבות ותנאים שבהם אפשר לקבל או לדחות את הגישה.

בכללי ברירת המחדל, ביטוי match הראשון משתמש בביטוי {bucket} כתובת Wildcard כדי לציין שהכללים חלים על כל הקטגוריות בפרויקט. נעסוק בנושא הזה בהרחבה בקטע הבא.

service firebase.storage {
  // The {bucket} wildcard indicates we match files in all Cloud Storage buckets
  match /b/{bucket}/o {
    // Match filename
    match /filename {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

כל הצהרות ההתאמה מפנות לקבצים. הצהרת התאמה יכולה להצביע על שלך, כמו match /images/profilePhoto.png.

התאמה של תווים כלליים לחיפוש

בנוסף להפניה לקובץ יחיד, אפשר להשתמש ב-Rules עם תווים כלליים לחיפוש כדי להפנות לכל קובץ עם קידומת מחרוזת נתונה בשם שלו, כולל קווים נטויים, כמו ב-match /images/{imageId}.

בדוגמה שלמעלה, הצהרת ההתאמה משתמשת בתחביר של התו הכללי לחיפוש {imageId}. כלומר, הכלל חל על כל קובץ ש-/images/ מופיע בתחילת השם שלו, כמו /images/profilePhoto.png או /images/croppedProfilePhoto.png. כאשר מתבצעת הערכה של allow ביטויים בהצהרת ההתאמה, המשתנה imageId יהפוך לשם קובץ התמונה, למשל profilePhoto.png או croppedProfilePhoto.png

כדי לספק קובץ, אפשר להפנות למשתנה עם תו כללי לחיפוש מתוך match הרשאת שם או נתיב:

// Another way to restrict the name of a file
match /images/{imageId} {
  allow read: if imageId == "profilePhoto.png";
}

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

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

קחו לדוגמה את המצב של קבוצת קבצים שהשמות שלהם מתחילים ב- שורש /images/. Firebase Security Rules חלים רק על שם הקובץ התואם, כך שאמצעי בקרת הגישה שמוגדרים בבסיס /images/ לא חלים על הבסיס /mp3s/. במקום זאת, כדאי לכתוב כללים מפורשים שתואמים לתבניות שונות של שמות קבצים:

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      allow read, write: if <condition>;
    }

    // Explicitly define rules for the 'mp3s' pattern
    match /mp3s/{mp3Id} {
      allow read, write: if <condition>;
    }
  }
}

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

service firebase.storage {
  match /b/{bucket}/o {
    match /images {
      // Exact match for "images/profilePhoto.png"
      match /profilePhoto.png {
        allow write: if <condition>;
      }
    }
  }
}
service firebase.storage {
  match /b/{bucket}/o {
    // Exact match for "images/profilePhoto.png"
    match /images/profilePhoto.png {
      allow write: if <condition>;
      }
  }
}

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

בנוסף לתווים כלליים לחיפוש שתואמים למחרוזות ומחזירים מחרוזות בסוף שם קובץ, אפשר להצהיר על תו כללי לחיפוש עם מספר קטעים לצורך התאמה מורכבת יותר באמצעות הוספה של =** לשם התו הכללי לחיפוש, כמו {path=**}:

// Partial match for files that start with "images"
match /images {

  // 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.

Cloud Storage Security Rules לא מדורגים, והכללים נבדקים רק כאשר נתיב הבקשה תואם לנתיב שצוינו בכללים.

גרסה 1

Firebase Security Rules משתמשים בגרסה 1 כברירת מחדל. בגרסה 1, תווים כלליים רפלקסיביים תואמים לרכיב אחד או יותר של שם הקובץ, ולא לאפס רכיבים או יותר. לכן, match /images/{filenamePrefixWildcard}/{imageFilename=**} תואם לשם קובץ כמו ‎/images/profilePics/profile.png, אבל לא ל-‎/images/badge.png. במקום זאת, אתם צריכים להשתמש ב-/images/{imagePrefixorFilename=**}.

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

מומלץ להשתמש בגרסה 2 בגלל התכונות המתקדמות יותר שלה.

גרסה 2

בגרסה 2 של Firebase Security Rules, תווים כלליים לחיפוש רקורסיביים תואמים לאפס נתיב או יותר פריטים. לכן, הערך /images/{filenamePrefixWildcard}/{imageFilename=**} תואם לשמות הקבצים ‎/images/profilePics/profile.png ו-‎/images/badge.png.

צריך להצטרף לגרסה 2. לשם כך, מוסיפים את rules_version = '2'; בחלק העליון של כללי האבטחה שלך:

rules_version = '2';
service cloud.storage {
  match /b/{bucket}/o {
   ...
 }
}

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

rules_version = '2';
service firebase.storage {
 match /b/{bucket}/o {
   // Matches any file in a songs "subdirectory" under the
   // top level of your Cloud Storage bucket.
   match /{prefixSegment=**}/songs/{mp3filenames} {
     allow read, write: if <condition>;
   }
  }
}

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

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

אפשר לפצל פעולת read ל-get ול-list.

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

service firebase.storage {
  match /b/{bucket}/o {
    // A read rule can be divided into read and list rules
    match /images/{imageId} {
      // Applies to single file read requests
      allow get: if <condition>;
      // Applies to list and listAll requests (Rules Version 2)
      allow list: if <condition>;

    // A write rule can be divided into create, update, and delete rules
    match /images/{imageId} {
      // Applies to writes to file contents
      allow create: if <condition>;

      // Applies to updates to (pre-existing) file metadata
      allow update: if <condition>;

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

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

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

service firebase.storage {
  match b/{bucket}/o {
    // Matches file names directly inside of '/images/'.
    match /images/{imageId} {
      allow read, write: if false;
    }

    // Matches file names anywhere under `/images/`
    match /images/{imageId=**} {
      allow read, write: if true;
    }
  }
}

בדוגמה שלמעלה, כל המשתמשים נקראו וכותבים בקבצים ששמם מתחיל ב- /images/ מותרים כי הכלל השני הוא תמיד true, גם כאשר הכלל הראשון הוא false.

כללים הם לא מסננים

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

לדוגמה, כלל האבטחה הבא:

service firebase.storage {
  match /b/{bucket}/o {
    // Allow the client to read files with contentType 'image/png'
    match /aFileNamePrefix/{aFileName} {
      allow read: if resource.contentType == 'image/png';
    }
  }
}

נדחתה: הכלל הזה דוחה את הפריטים הבאים כי קבוצת התוצאות יכולה לכלול קבצים שבהם contentType לא image/png:

אינטרנט
filesRef = storage.ref().child("aFilenamePrefix");

filesRef.listAll()
    .then(function(result) {
      console.log("Success: ", result.items);
    })
});

הכללים ב-Cloud Storage Security Rules מעריכים כל שאילתה מול הפוטנציאל שלה התוצאה והיא נכשלת אם היא יכולה להחזיר קובץ שהלקוח מבצע אין הרשאת קריאה. בקשות הגישה חייבות לעמוד באילוצים שהוגדרו בכללים.

השלבים הבאים

כדי להבין טוב יותר את Firebase Security Rules ב-Cloud Storage:

אפשר לעיין בתרחישי לדוגמה של Firebase Security Rules שספציפיים ל-Cloud Storage: