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

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

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

אימות

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

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to access documents in the "cities" collection
    // only if they are authenticated.
    match /cities/{city} {
      allow read, write: if request.auth != null;
    }
  }
}

דפוס נפוץ נוסף הוא לוודא שמשתמשים יכולים לקרוא ולכתוב רק נתונים משלהם:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, update, delete: if request.auth != null && request.auth.uid == userId;
      allow create: if request.auth != null;
    }
  }
}

אם האפליקציה משתמשת אימות Firebase או Google Cloud זהות פלטפורמה , את request.auth המשתנה מכיל את המידע אימות עבור הלקוח מבקש נתונים. לקבלת מידע נוסף אודות request.auth , לראות בתיעוד העזר .

אימות מידע

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

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

resource משתנה מתייחס המסמך המבוקש, resource.data היא מפה של כל השדות והערכים מאוחסן המסמך. לקבלת מידע נוסף על resource משתנה, לראות בתיעוד העזר .

בעת כתיבת נתונים, ייתכן שתרצה להשוות נתונים נכנסים לנתונים קיימים. במקרה זה, אם מערכת כללים שלך מאפשר כתיבה תלויה ועומדת, request.resource המשתנה מכיל את המדינה בעתיד של המסמך. לקבלת update פעולות שרק לשנות משנה של שדות המסמך, request.resource משתנה יכיל את מדינת מסמך בהמתנה לאחר הניתוח. אתה יכול לבדוק את ערכי שדה request.resource למנוע עדכוני נתונים לא רצוי או לא עקביים:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure all cities have a positive population and
    // the name is not changed
    match /cities/{city} {
      allow update: if request.resource.data.population > 0
                    && request.resource.data.name == resource.data.name;
    }
  }
}

גש למסמכים אחרים

באמצעות get() ו exists() פונקציות, כללי הביטחון שלך יכולים להעריך בקשות נכנסות כנגד מסמכים אחרים באתר. get() ו exists() פונקציות היא לצפות נתיבי מסמך שצוינו מלא. בעת שימוש במשתנים לנתיבי מבנה עבור get() ו exists() , אתה צריך לברוח במפורש משתנה באמצעות $(variable) התחביר.

בדוגמה להלן, database משתנה הוא נתפס על ידי אמירה המשחק match /databases/{database}/documents והשתמש כדי ליצור את הנתיב:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      // Make sure a 'users' document exists for the requesting user before
      // allowing any writes to the 'cities' collection
      allow create: if request.auth != null && exists(/databases/$(database)/documents/users/$(request.auth.uid))

      // Allow the user to delete cities if their user document has the
      // 'admin' field set to 'true'
      allow delete: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
    }
  }
}

עבור כותב, אתה יכול להשתמש getAfter() הפונקציה לגשת מדינת מסמך לאחר עסקה או תצווה של כותב משלים אך לפני יתחייב העסקה או תצווה. כמו get() , את getAfter() הפונקציה לוקחת נתיב מסמך שצוין מלא. אתה יכול להשתמש getAfter() כדי להגדיר קבוצות של כותב כי חייב להתקיים ביחד כעסקה או אצווה.

הגבלת שיחות גישה

יש הגבלה על שיחות גישה למסמכים לכל הערכה של מערכת כללים:

  • 10 לבקשות של מסמך יחיד ובקשות שאילתה.
  • 20 עבור קריאה מרובה מסמכים, עסקאות וכתיבה בקבוצות. המגבלה הקודמת של 10 חלה גם על כל פעולה.

    לדוגמה, דמיין שאתה יוצר בקשת כתיבה באצווה עם 3 פעולות כתיבה ושכללי האבטחה שלך משתמשים בשתי שיחות גישה למסמכים כדי לאמת כל כתיבה. במקרה זה, כל כתיבה משתמשת ב -2 מתוך 10 שיחות הגישה שלה ובקשת הכתיבה המצוות משתמשת ב -6 מתוך 20 שיחות הגישה שלה.

חריגה ממגבלה גורמת לשגיאת שלילת הרשאה. חלק משיחות גישה למסמכים עשויות להישמר במטמון, ושיחות במטמון אינן נחשבות לגבול.

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

גישה לשיחות ותמחור

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

פונקציות בהתאמה אישית

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

  • פונקציות יכולות להכיל אחת בלבד return בהצהרה. הם אינם יכולים להכיל היגיון נוסף. לדוגמה, הם אינם יכולים לבצע לולאות או להתקשר לשירותים חיצוניים.
  • פונקציות יכולות לגשת אוטומטית לפונקציות ולמשתנים מההיקף שבו הן מוגדרות. לדוגמה, פונקציה המוגדרת בתוך service cloud.firestore ההיקף לו גישה resource משתנה מובנה פונקציות כגון get() ו exists() .
  • פונקציות עשויות לכנות פונקציות אחרות אך אינן יכולות לחזור על עצמן. העומק הכולל של ערימת השיחות מוגבל ל -10.
  • בגרסת כללי v2 , פונקציות יכולות להגדיר משתנות באמצעות let מילות המפתח. פונקציות יכולות להכיל עד 10 כריכות אישור, אך חייבות להסתיים בהצהרת החזרה.

פונקציה מוגדרת עם function המילה ולוקחת אפס או יותר ויכוחים. לדוגמה, ייתכן שתרצה לשלב את שני סוגי התנאים המשמשים בדוגמאות לעיל לפונקציה אחת:

service cloud.firestore {
  match /databases/{database}/documents {
    // 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 /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

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

חוקים אינם מסננים

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

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

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

נדחתה: כלל זה דוחה את השאילתה הבאה משום להגדיר התוצאה יכולה לכלול מסמכים שבהם visibility אינה public :

אינטרנט
db.collection("cities").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
    });
});

למלון: כלל זה מאפשר את שאילתא הבאה משום where("visibility", "==", "public") ערבויות סעיף זה להגדיר תוצאה עונה על התנאי של הכלל:

אינטרנט
db.collection("cities").where("visibility", "==", "public").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
        });
    });

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

הצעדים הבאים