ساختار قوانین امنیتی Cloud Firestore

Cloud Firestore Security Rules به شما امکان کنترل دسترسی به اسناد و مجموعه‌ها در پایگاه داده خود را می‌دهند. سینتکس انعطاف‌پذیر قوانین به شما امکان می‌دهد قوانینی ایجاد کنید که با هر چیزی مطابقت داشته باشند، از همه نوشتن‌ها در کل پایگاه داده گرفته تا عملیات روی یک سند خاص.

این راهنما، سینتکس و ساختار اولیه‌ی قوانین امنیتی را شرح می‌دهد. این سینتکس را با شرایط قوانین امنیتی ترکیب کنید تا مجموعه قوانین کاملی ایجاد شود.

اعلان سرویس و پایگاه داده

Cloud Firestore Security Rules همیشه با عبارت زیر شروع می‌شوند:

service cloud.firestore {
  // The {database} wildcard allows the rules to reference any database,
  // but these rules are only active on databases where they are explicitly deployed.
  match /databases/{database}/documents {
    // ...
  }
}

اعلان service cloud.firestore قوانین را به Cloud Firestore محدود می‌کند و از تداخل بین Cloud Firestore Security Rules و قوانین سایر محصولات مانند Cloud Storage جلوگیری می‌کند.

عبارت match /databases/{database}/documents مشخص می‌کند که قوانین باید با هر پایگاه داده Cloud Firestore در پروژه مطابقت داشته باشند. در حالی که یک پروژه می‌تواند تا ۱۰۰ پایگاه داده داشته باشد، فقط اولین پایگاه داده ایجاد شده به عنوان پیش‌فرض تعیین می‌شود.

Cloud Firestore Security Rules برای هر پایگاه داده نامگذاری شده در پروژه شما به طور جداگانه اعمال می‌شوند. این بدان معناست که اگر چندین پایگاه داده ایجاد می‌کنید، باید قوانین را برای هر یک به صورت جداگانه مدیریت و مستقر کنید. برای دستورالعمل‌های دقیق در مورد استقرار به‌روزرسانی‌های خود، به بخش استقرار به‌روزرسانی‌های خود مراجعه کنید.

قوانین اساسی خواندن/نوشتن

قوانین اساسی شامل یک عبارت match است که مسیر سند را مشخص می‌کند و یک عبارت allow که جزئیات مربوط به زمان مجاز خواندن داده‌های مشخص شده را شرح می‌دهد:

service cloud.firestore {
  match /databases/{database}/documents {

    // Match any document in the 'cities' collection
    match /cities/{city} {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

همه دستورات match باید به اسناد اشاره کنند، نه مجموعه‌ها. یک دستور match می‌تواند به یک سند خاص اشاره کند، مانند match /cities/SF یا از کاراکترهای wildcard برای اشاره به هر سندی در مسیر مشخص شده استفاده کند، مانند match /cities/{city} .

در مثال بالا، دستور match از سینتکس wildcard {city} استفاده می‌کند. این بدان معناست که این قانون برای هر سندی در مجموعه cities ، مانند /cities/SF یا /cities/NYC ، اعمال می‌شود. هنگامی که عبارات allow در دستور match ارزیابی می‌شوند، متغیر city به نام سند city، مانند SF یا NYC ، تبدیل می‌شود.

عملیات دانه‌ای

در برخی شرایط، تجزیه read و write به عملیات جزئی‌تر مفید است. برای مثال، ممکن است برنامه شما بخواهد شرایط متفاوتی را برای ایجاد سند نسبت به حذف سند اعمال کند. یا ممکن است بخواهید خواندن یک سند را مجاز کنید اما درخواست‌های بزرگ را رد کنید.

یک قانون read را می‌توان به get و list تقسیم کرد، در حالی که یک قانون write را می‌توان به create ، update و delete تقسیم کرد:

service cloud.firestore {
  match /databases/{database}/documents {
    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if <condition>;

      // Applies to queries and collection read requests
      allow list: if <condition>;
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if <condition>;

      // Applies to writes to existing documents
      allow update: if <condition>;

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

داده‌های سلسله مراتبی

داده‌ها در Cloud Firestore در مجموعه‌ای از اسناد سازماندهی شده‌اند و هر سند می‌تواند سلسله مراتب را از طریق زیرمجموعه‌ها گسترش دهد. درک چگونگی تعامل قوانین امنیتی با داده‌های سلسله مراتبی مهم است.

وضعیتی را در نظر بگیرید که هر سند در مجموعه cities شامل یک زیرمجموعه landmarks باشد. قوانین امنیتی فقط در مسیر منطبق اعمال می‌شوند، بنابراین کنترل‌های دسترسی تعریف شده در مجموعه cities به زیرمجموعه landmarks اعمال نمی‌شوند. در عوض، قوانین صریحی برای کنترل دسترسی به زیرمجموعه‌ها بنویسید:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      allow read, write: if <condition>;

        // Explicitly define rules for the 'landmarks' subcollection
        match /landmarks/{landmark} {
          allow read, write: if <condition>;
        }
    }
  }
}

هنگام تودرتو کردن دستورات match ، مسیر دستور match داخلی همیشه نسبت به مسیر دستور match خارجی است. بنابراین، مجموعه قوانین زیر معادل هستند:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}
service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city}/landmarks/{landmark} {
      allow read, write: if <condition>;
    }
  }
}

نویسه‌های عام بازگشتی

اگر می‌خواهید قوانین به یک سلسله مراتب دلخواه عمیق اعمال شوند، از سینتکس بازگشتی wildcard، {name=**} استفاده کنید. برای مثال:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

هنگام استفاده از سینتکس بازگشتی wildcard، متغیر wildcard شامل کل بخش مسیر منطبق خواهد بود، حتی اگر سند در یک زیرمجموعه عمیقاً تو در تو قرار داشته باشد. برای مثال، قوانین ذکر شده در بالا با سندی که در /cities/SF/landmarks/coit_tower قرار دارد، مطابقت دارند و مقدار متغیر document SF/landmarks/coit_tower خواهد بود.

با این حال، توجه داشته باشید که رفتار کاراکترهای جایگزین بازگشتی به نسخه قوانین بستگی دارد.

نسخه ۱

قوانین امنیتی به طور پیش‌فرض از نسخه ۱ استفاده می‌کنند. در نسخه ۱، کاراکترهای جایگزین بازگشتی با یک یا چند مورد مسیر مطابقت دارند. آن‌ها با یک مسیر خالی مطابقت ندارند، بنابراین match /cities/{city}/{document=**} با اسناد موجود در زیرمجموعه‌ها مطابقت دارد اما با اسناد موجود در مجموعه cities مطابقت ندارد، در حالی که match /cities/{document=**} با هر دو سند موجود در مجموعه cities و زیرمجموعه‌ها مطابقت دارد.

کاراکترهای جایگزین بازگشتی باید در انتهای یک دستور match قرار گیرند.

نسخه ۲

در نسخه ۲ قوانین امنیتی، کاراکترهای جایگزین بازگشتی با صفر یا چند مورد مسیر مطابقت دارند. match/cities/{city}/{document=**} اسناد را در هر زیرمجموعه و همچنین اسناد موجود در مجموعه cities مطابقت می‌دهد.

شما باید با اضافه کردن rules_version = '2'; در بالای قوانین امنیتی خود، نسخه ۲ را فعال کنید:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{city}/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

شما می‌توانید حداکثر یک کاراکتر جایگزین بازگشتی برای هر دستور match داشته باشید، اما در نسخه ۲، می‌توانید این کاراکتر جایگزین را در هر جایی از دستور match قرار دهید. برای مثال:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the songs collection group
    match /{path=**}/songs/{song} {
      allow read, write: if <condition>;
    }
  }
}

اگر از کوئری‌های گروه‌های مجموعه استفاده می‌کنید، باید از نسخه ۲ آن استفاده کنید، به بخش ایمن‌سازی کوئری‌های گروه‌های مجموعه مراجعه کنید.

همپوشانی دستورات تطابق

ممکن است یک سند با بیش از یک عبارت match مطابقت داشته باشد. در صورتی که چندین عبارت allow با یک درخواست مطابقت داشته باشند، در صورت true بودن هر یک از شرایط زیر، دسترسی مجاز است:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the 'cities' collection.
    match /cities/{city} {
      allow read, write: if false;
    }

    // Matches any document in the 'cities' collection or subcollections.
    match /cities/{document=**} {
      allow read, write: if true;
    }
  }
}

در مثال بالا، تمام خواندن‌ها و نوشتن‌ها در مجموعه cities مجاز خواهد بود زیرا قانون دوم همیشه true است، حتی اگر قانون اول همیشه false باشد.

محدودیت‌های قانون امنیتی

هنگام کار با قوانین امنیتی، به محدودیت‌های زیر توجه کنید:

حد جزئیات
حداکثر تعداد فراخوانی‌های exists() ، get() و getAfter() به ازای هر درخواست
  • ۱۰ برای درخواست‌های تک سندی و درخواست‌های استعلام.
  • ۲۰ برای خواندن‌های چند سندی، تراکنش‌ها و نوشتن‌های دسته‌ای. محدودیت قبلی ۱۰ برای هر عملیات نیز اعمال می‌شود.

    برای مثال، تصور کنید که یک درخواست نوشتن دسته‌ای با ۳ عملیات نوشتن ایجاد می‌کنید و قوانین امنیتی شما از ۲ فراخوانی دسترسی به سند برای اعتبارسنجی هر نوشتن استفاده می‌کنند. در این حالت، هر نوشتن از ۲ فراخوانی از ۱۰ فراخوانی دسترسی خود استفاده می‌کند و درخواست نوشتن دسته‌ای از ۶ فراخوانی از ۲۰ فراخوانی دسترسی خود استفاده می‌کند.

تجاوز از هر یک از این محدودیت‌ها منجر به خطای عدم اجازه دسترسی می‌شود.

برخی از فراخوانی‌های دسترسی به سند ممکن است در حافظه پنهان ذخیره شوند و فراخوانی‌های ذخیره شده در حافظه پنهان جزو محدودیت‌ها محسوب نمی‌شوند.

حداکثر عمق عبارت match تو در تو ۱۰
حداکثر طول مسیر، در بخش‌های مسیر، مجاز در مجموعه‌ای از دستورات match تو در تو ۱۰۰
حداکثر تعداد متغیرهای ثبت مسیر مجاز در مجموعه‌ای از دستورات match تو در تو ۲۰
حداکثر عمق فراخوانی تابع ۲۰
حداکثر تعداد آرگومان‌های تابع ۷
حداکثر تعداد متغیرهای let برای هر تابع ۱۰
حداکثر تعداد فراخوانی‌های تابع بازگشتی یا چرخه‌ای ۰ (مجاز نیست)
حداکثر تعداد عبارات ارزیابی شده در هر درخواست ۱۰۰۰
حداکثر اندازه یک مجموعه قوانین مجموعه قوانین باید از دو محدودیت اندازه پیروی کنند:
  • محدودیت ۲۵۶ کیلوبایتی برای اندازه منبع متن مجموعه قوانین منتشر شده از کنسول Firebase یا از رابط خط فرمان (CLI) با استفاده از firebase deploy .
  • محدودیت ۲۵۰ کیلوبایتی برای اندازه مجموعه قوانین کامپایل‌شده که هنگام پردازش منبع توسط فایربیس و فعال کردن آن در بک‌اند ایجاد می‌شود.

مراحل بعدی