מדריך זה מתבסס על לימוד תחביר הליבה של מדריך השפה של Firebase Security Rules כדי להראות כיצד להוסיף תנאים לכללי האבטחה של Firebase עבור אחסון ענן.
אבן הבניין העיקרית של כללי האבטחה של Cloud Storage הוא התנאי . תנאי הוא ביטוי בוליאני שקובע אם יש לאפשר או לדחות פעולה מסוימת. לגבי כללים בסיסיים, שימוש במילולי true
false
כתנאים עובד מצוין. אבל כללי האבטחה של Firebase עבור שפת Cloud Storage נותנים לך דרכים לכתוב תנאים מורכבים יותר שיכולים:
- בדוק את אימות המשתמש
- אימות נתונים נכנסים
אימות
כללי האבטחה של Firebase עבור Cloud Storage משתלבים עם Firebase Authentication כדי לספק אימות מבוסס משתמשים רב עוצמה ל-Cloud Storage. זה מאפשר בקרת גישה פרטנית המבוססת על תביעות של אסימון Firebase Authentication.
כאשר משתמש מאומת מבצע בקשה נגד Cloud Storage, המשתנה request.auth
מאוכלס ב- uid
של המשתמש ( request.auth.uid
) וכן בטענות של Firebase Authentication JWT ( 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. בנוסף למזהה הייחודי של המשתמש ולעומס ה-Firebase Authentication באובייקט request.auth
כמתואר לעיל, משתנה request
מכיל את נתיב הקובץ שבו מתבצעת הבקשה, את השעה שבה הבקשה מתקבלת, ואת ערך resource
החדש אם הבקשה היא כתיבה.
אובייקט request
מכיל גם את המזהה הייחודי של המשתמש ואת מטען האימות של Firebase באובייקט request.auth
, שיוסבר עוד בסעיף אבטחה מבוססת משתמש של המסמכים.
רשימה מלאה של מאפיינים באובייקט request
זמינה להלן:
תכונה | סוּג | תיאור |
---|---|---|
auth | map<string, string> | כאשר משתמש מחובר, מספק uid , המזהה הייחודי token של המשתמש, טוענת מפה של Firebase Authentication JWT. אחרת, הוא יהיה null . |
params | map<string, string> | מפה המכילה את פרמטרי השאילתה של הבקשה. |
path | נָתִיב | path המייצג את הנתיב שבו מבוצעת הבקשה. |
resource | map<string, string> | ערך המשאב החדש, קיים רק בבקשות write . |
time | חותמת זמן | חותמת זמן המייצגת את זמן השרת שבו הבקשה מוערכת. |
הערכת משאבים
בעת הערכת כללים, ייתכן שתרצה גם להעריך את המטא נתונים של הקובץ המועלה, הורדה, שינוי או מחיקה. זה מאפשר לך ליצור כללים מורכבים וחזקים שעושים דברים כמו לאפשר רק להעלות קבצים עם סוגי תוכן מסוימים, או למחוק רק קבצים גדולים מגודל מסוים.
כללי האבטחה של Firebase עבור 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 | חוּט | Hash MD5 של האובייקט. |
crc32c | חוּט | hash 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()
, עליך להימלט במפורש למשתנים באמצעות התחביר $(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 המשתמשים בפונקציות האלה של Cloud Firestore, תתבקש במסוף Firebase או Firebase CLI לאפשר הרשאות לחיבור שני המוצרים.
אתה יכול להשבית את התכונה על ידי הסרת תפקיד IAM, כמתואר בניהול ופריסה של כללי אבטחה של Firebase .
אמת נתונים
ניתן להשתמש בכללי האבטחה של Firebase עבור אחסון בענן גם לאימות נתונים, כולל אימות שם קובץ ונתיב, כמו גם מאפייני מטא נתונים של קבצים כגון 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 הופכים מורכבים יותר, ייתכן שתרצה לעטוף קבוצות של תנאים בפונקציות שתוכל לעשות בהן שימוש חוזר בכל מערכת הכללים שלך. כללי אבטחה תומכים בפונקציות מותאמות אישית. התחביר של פונקציות מותאמות אישית דומה קצת ל-JavaScript, אבל פונקציות כללי האבטחה של Firebase כתובות בשפה ספציפית לתחום שיש לה כמה מגבלות חשובות:
- פונקציות יכולות להכיל רק הצהרת
return
אחת. הם לא יכולים להכיל שום היגיון נוסף. לדוגמה, הם לא יכולים לבצע לולאות או להתקשר לשירותים חיצוניים. - פונקציות יכולות לגשת אוטומטית לפונקציות ומשתנים מההיקף שבו הן מוגדרות. לדוגמה, לפונקציה המוגדרת בהיקף
service firebase.storage
יש גישה למשתנהresource
, ול-Cloud Firestore בלבד, פונקציות מובנות כגוןget()
ו-exists()
. - פונקציות עשויות לקרוא לפונקציות אחרות אך לא יחזרו. עומק השיחות הכולל מוגבל ל-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 הופך אותם לניתנים יותר לתחזוקה ככל שהמורכבות של הכללים שלך גדלה.
הצעדים הבאים
לאחר הדיון הזה בתנאים, יש לך הבנה מתוחכמת יותר של הכללים ואתה מוכן:
למד כיצד לטפל במקרים בסיסיים של שימוש, ולמד את זרימת העבודה לפיתוח, בדיקה ופריסה של כללים:
- כתוב כללים המתייחסים לתרחישים נפוצים .
- בנה על הידע שלך על ידי סקירת מצבים שבהם אתה חייב לזהות חוקים לא בטוחים ולהימנע מהם .
- בדיקת חוקים באמצעות אמולטור Cloud Storage וספריית בדיקה ייעודית של כללי אבטחה .
- סקור את השיטות הזמינות לפריסת כללים .