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

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

במדריך הזה מוסברים התחביר והמבנה הבסיסיים של 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/ stem לא חלים על /mp3s/ stem. במקום זאת, כותבים כללים מפורשים שתואמים לתבניות שונות של שמות קבצים:

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 שמתייחסות אליהם.

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