המדריך הזה מבוסס על לומדים את התחביר הבסיסי של המדריך לשפת Firebase Security Rules כדי להראות איך להוסיף תנאים ל-Firebase Security Rules עבור Cloud Storage.
אבן הבניין הראשית של Cloud Storage Security Rules הוא התנאי. א'
הוא ביטוי בוליאני שקובע אם פעולה מסוימת
מותר או לדחות. לכללים בסיסיים, יש להשתמש בליטרל true
ובליטרל false
כי התנאים פועלים בצורה מושלמת. אבל Firebase Security Rules של Cloud Storage
שפה מספקת דרכים לכתוב תנאים מורכבים יותר שיכולים:
- בדיקת אימות המשתמש
- אימות הנתונים הנכנסים
אימות
Firebase Security Rules ל-Cloud Storage משתלב עם Firebase Authentication כדי לספק אימות מבוסס-משתמשים רב עוצמה ל-Cloud Storage. כך אפשר לבצע בקרת גישה מפורטת על סמך הצהרות של אסימון Firebase Authentication.
כשמשתמש מאומת שולח בקשה נגד Cloud Storage,
המשתנה request.auth
מאוכלס ב-uid
של המשתמש
(request.auth.uid
) וכן להצהרות של JWT Firebase Authentication
(request.auth.token
).
בנוסף, כשמשתמשים באימות מותאם אישית, יוצגו תלונות נוספות
בשדה request.auth.token
.
כשמשתמש לא מאומת מבצע בקשה, המשתנה request.auth
הוא null
.
באמצעות הנתונים האלה, יש כמה דרכים נפוצות להשתמש באימות כדי קבצים:
- ציבורי: התעלמות מ-
request.auth
- פרטי מאומת: יש לוודא ש-
request.auth
אינוnull
- משתמש פרטי: בודקים ש-
request.auth.uid
שווה לנתיבuid
- פרטי קבוצה: בודקים אם הצהרות האסימון המותאם אישית תואמות להצהרה שנבחרה, או קוראים את המטא-נתונים של הקובץ כדי לראות אם קיים שדה מטא-נתונים
גלוי לכולם
כל כלל שלא מתייחס להקשר של request.auth
יכול להיחשב
public
, כי הוא לא מביא בחשבון את הקשר האימות של המשתמש.
הכללים האלה יכולים להיות שימושיים להצגת נתונים ציבוריים, כמו נכסי משחקים, צלילים
קבצים או תוכן סטטי אחר.
// Anyone to read a public image if the file is less than 100kB // Anyone can upload a public file ending in '.txt' match /public/{imageId} { allow read: if resource.size < 100 * 1024; allow write: if imageId.matches(".*\\.txt"); }
פרטי מאומת,
במקרים מסוימים, ייתכן שתרצו שהנתונים יהיו גלויים לכל המשתמשים המאומתים של
את האפליקציה שלך, אבל לא על ידי משתמשים לא מאומתים. מאז request.auth
המשתנה הוא null
עבור כל המשתמשים הלא מאומתים, כל מה שצריך לעשות הוא לבדוק
המשתנה request.auth
קיים כדי לדרוש אימות:
// Require authentication on all internal image reads match /internal/{imageId} { allow read: if request.auth != null; }
פרטי למשתמש
עד עכשיו, התרחיש לדוגמה הנפוץ ביותר של request.auth
הוא מתן
משתמשים עם הרשאות מפורטות לקבצים שלהם: מהעלאת תמונות פרופיל
לקריאת מסמכים פרטיים.
לקבצים ב-Cloud Storage יש 'נתיב' מלא לקובץ, כל מה שצריך
ליצירת קובץ שנשלט על ידי משתמש הוא קטע
מידע בקידומת שם הקובץ (למשל uid
של המשתמש) שיכול להיות
כשמתבצעת הערכה של הכלל:
// Only a user can upload their profile picture, but anyone can view it match /users/{userId}/profilePicture.png { allow read; allow write: if request.auth.uid == userId; }
קבוצה פרטית
תרחיש נוסף נפוץ לא פחות הוא מתן הרשאות לקבוצה באובייקט, למשל, לאפשר לכמה חברי צוות לעבוד ביחד על מסמך משותף. יש יש כמה גישות לעשות זאת:
- הטבעת אסימון בהתאמה אישית של Firebase Authentication שמכיל מידע נוסף על חבר קבוצה (כמו מזהה קבוצה)
- הכללת פרטי קבוצה (כמו מזהה קבוצה או רשימה של משתמשים מורשים
uid
) ב- את המטא-נתונים של הקובץ
אחרי שהנתונים האלה מאוחסנים באסימון או במטא-נתונים של הקובץ, אפשר להפנות אליהם מתוך כלל:
// Allow reads if the group ID in your token matches the file metadata's `owner` property // Allow writes if the group ID is in the user's custom token match /files/{groupId}/{fileName} { allow read: if resource.metadata.owner == request.auth.token.groupId; allow write: if request.auth.token.groupId == groupId; }
בקשה להערכה
המערכת מבצעת הערכה של העלאות, הורדות, שינויים במטא-נתונים ומחיקות באמצעות הערך של request
שנשלח אל Cloud Storage. בנוסף למזהה הייחודי של המשתמש ול
המטען הייעודי (payload) של Firebase Authentication באובייקט request.auth
כמו שמתואר למעלה,
המשתנה request
מכיל את נתיב הקובץ שבו הבקשה מועברת
בוצעו, השעה שבה הבקשה מתקבלת והערך resource
החדש
אם הבקשה היא כתיבה.
האובייקט request
מכיל גם את המזהה הייחודי של המשתמש ואת עומס העבודה (payload) של Firebase Authentication באובייקט request.auth
. מידע נוסף זמין בקטע אבטחה מבוססת-משתמשים במסמכים.
רשימה מלאה של המאפיינים באובייקט request
זמינה בהמשך:
נכס | סוג | תיאור |
---|---|---|
auth |
מפה<string, string> | כשמשתמש מחובר לחשבון, הוא מספק את uid , המזהה הייחודי של המשתמש, וגם את token , מפה של Firebase Authentication הצהרות JWT. אחרת,
null |
params |
map<string, string> | מפה שמכילה את פרמטרים השאילתה של הבקשה. |
path |
נתיב | path שמייצג את הנתיב שבו מתבצעת הבקשה. |
resource |
מפה<string, string> | ערך המשאב החדש, שנמצא רק בבקשות write .
|
time |
חותמת זמן | חותמת זמן שמייצגת את הזמן שבו מתבצעת בדיקת הבקשה בשרת. |
הערכת משאבים
כשבוחנים כללים, מומלץ גם להעריך את המטא-נתונים של הקובץ העלאות, הורדה, שינוי או מחיקה. כך אפשר ליצור הם כללים מורכבים וחזקים שעושים דברים כמו לאפשר רק קבצים עם מאפיינים מסוימים סוגי תוכן להעלאה, או רק קבצים שגדולים מגודל מסוים נמחק.
Firebase Security Rules עבור Cloud Storage מספק מטא-נתונים של קובץ באובייקט resource
, שמכיל צמדי מפתח/ערך של המטא-נתונים שמוצגים באובייקט Cloud Storage. אפשר לבדוק את המאפיינים האלה ב-read
או
בקשות write
כדי להבטיח את תקינות הנתונים.
בבקשות write
(כמו העלאות, עדכוני מטא-נתונים ומחיקה), בנוסף לאובייקט resource
שמכיל את המטא-נתונים של הקובץ שקיים כרגע בנתיב הבקשה, יש לכם גם אפשרות להשתמש באובייקט request.resource
שמכיל קבוצת משנה של המטא-נתונים של הקובץ שרוצים לכתוב אם הכתיבה מותרת. אפשר להשתמש בשני הערכים האלה כדי להבטיח
תקינות או אכיפת מגבלות של אפליקציה כגון סוג או גודל הקובץ.
רשימה מלאה של המאפיינים באובייקט resource
זמינה בהמשך:
נכס | סוג | תיאור |
---|---|---|
name |
מחרוזת | השם המלא של האובייקט |
bucket |
מחרוזת | שם הקטגוריה שבה נמצא האובייקט הזה. |
generation |
int | Google Cloud Storage של האובייקט הזה. |
metageneration |
int | מספר המטא-הדור של אובייקט Google Cloud Storage. |
size |
int | גודל האובייקט בבייטים. |
timeCreated |
חותמת זמן | חותמת זמן שמייצגת את השעה שבה האובייקט נוצר. |
updated |
חותמת זמן | חותמת זמן שמייצגת את הזמן שבו אובייקט עודכן לאחרונה. |
md5Hash |
מחרוזת | גיבוב MD5 של האובייקט. |
crc32c |
מחרוזת | גיבוב crc32c של האובייקט. |
etag |
מחרוזת | ה-etag שמשויך לאובייקט הזה. |
contentDisposition |
מחרוזת | צורת התוכן שמשויכת לאובייקט הזה. |
contentEncoding |
מחרוזת | קידוד התוכן שמשויך לאובייקט הזה. |
contentLanguage |
מחרוזת | שפת התוכן שמשויכת לאובייקט הזה. |
contentType |
מחרוזת | סוג התוכן שמשויך לאובייקט הזה. |
metadata |
map<string, string> | צמדי מפתח/ערך של מטא-נתונים מותאמים אישית נוספים שהמפתח ציין. |
השדה request.resource
מכיל את כל הערכים האלה, מלבד generation
, metageneration
, etag
, timeCreated
ו-updated
.
שיפור באמצעות Cloud Firestore
אפשר לגשת למסמכים ב-Cloud Firestore כדי להעריך קריטריונים אחרים להרשאה.
באמצעות הפונקציות firestore.get()
ו-firestore.exists()
, האבטחה שלך
כללים יכולים להעריך בקשות נכנסות מול מסמכים בCloud Firestore.
הפונקציות firestore.get()
והפונקציות firestore.exists()
מצפות באופן מלא
נתיבי מסמך שצוינו. כשמשתמשים במשתנים כדי לבנות נתיבים
firestore.get()
וגם firestore.exists()
, יש לסמן בתו בריחה (escape) באופן מפורש
משתנים באמצעות התחביר $(variable)
.
בדוגמה הבאה מוצג כלל שמגביל את הגישה לקריאת קבצים למשתמשים שהם חברים במועדונים מסוימים.
service firebase.storage { match /b/{bucket}/o { match /users/{club}/files/{fileId} { allow read: if club in firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships } } }
service firebase.storage { match /b/{bucket}/o { match /users/{userId}/photos/{fileId} { allow read: if firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id)) } } }
אחרי שיוצרים ושומרים את Cloud Storage Security Rules הראשונים שמשתמשים בCloud Firestore האלה הפונקציות, תופיע הודעה במסוף Firebase או ב-Firebase CLI כדי להפעיל את ההרשאות לחיבור בין שני המוצרים.
כדי להשבית את התכונה, מסירים תפקיד IAM, כפי שמתואר בקטע ניהול ופריסה של Firebase Security Rules.
אימות נתונים
אפשר להשתמש ב-Firebase Security Rules ל-Cloud Storage גם לאימות נתונים, כולל
אימות שם ונתיב של קובץ ומאפייני מטא נתונים של קבצים, כמו
contentType
וגם size
.
service firebase.storage { match /b/{bucket}/o { match /images/{imageId} { // Only allow uploads of any image file that's less than 5MB allow write: if request.resource.size < 5 * 1024 * 1024 && request.resource.contentType.matches('image/.*'); } } }
פונקציות מותאמות אישית
ככל שהFirebase Security Rules יהיה מורכב יותר, כדאי לעטוף קבוצות של בפונקציות שניתן לעשות בהן שימוש חוזר בכל קבוצת הכללים. כללי האבטחה תומכים בפונקציות בהתאמה אישית. התחביר של פונקציות מותאמות אישית דומה קצת ל-JavaScript, אבל הפונקציות של Firebase Security Rules כתובות בשפה ספציפית לדומיין עם כמה מגבלות חשובות:
- פונקציות יכולות להכיל רק הצהרת
return
אחת. הם לא יכולים להכיל לוגיקה נוספת. לדוגמה, הם לא יכולים להפעיל לולאות או להתקשר לשירותים חיצוניים. - פונקציות יכולות לגשת באופן אוטומטי לפונקציות ולמשתנים מההיקף שבו הן מוגדרות. לדוגמה, לפונקציה שמוגדרת בהיקף
service firebase.storage
יש גישה למשתנהresource
, ולפונקציות מובנות כמוget()
ו-exists()
רק בהיקף Cloud Firestore. - פונקציות יכולות לקרוא לפונקציות אחרות, אבל לא ניתן לחזור עליהן. עומק ה-call stack הכולל מוגבל ל-10.
- בגרסה
rules2
, פונקציות יכולות להגדיר משתנים באמצעות מילת המפתחlet
. פונקציות יכולות לכלול כל מספר קישורי let, אבל הן חייבות להסתיים בהצהרת return.
פונקציה מוגדרת עם מילת המפתח function
והיא מקבלת אפס או יותר
ארגומנטים. לדוגמה, תוכלו לשלב בין שני סוגי התנאים שבהם אתם משתמשים.
בדוגמאות שלמעלה, לפונקציה אחת:
service firebase.storage {
match /b/{bucket}/o {
// 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 /images/{imageId} {
allow read, write: if signedInOrPublic();
}
match /mp3s/{mp3Ids} {
allow read: if signedInOrPublic();
}
}
}
השימוש בפונקציות ב-Firebase Security Rules הופך אותן לקלות יותר בתור המורכבות של הכללים שלכם.
השלבים הבאים
אחרי הדיון על התנאים, להבין את הכללים והם מוכנים:
תלמדו איך לטפל בתרחישים עיקריים לדוגמה, ותלמדו את תהליך הפיתוח של של כללים לבדיקה ופריסה:
- כתבו כללים שמתייחסים לתרחישים נפוצים.
- מרחיבים את הידע על ידי בדיקה של מצבים שבהם צריך לזהות כללים לא מאובטחים ולהימנע מהם.
- בודקים את הכללים באמצעות האמולטור Cloud Storage וספריית הבדיקות הייעודית של כללי אבטחה.
- אפשר לעיין בשיטות הזמינות לפריסה של Rules.