زبان قوانین امنیتی

Firebase Security Rules از زبان‌های منعطف، قدرتمند و سفارشی استفاده می‌کند که از طیف وسیعی از پیچیدگی و جزئیات پشتیبانی می‌کنند. شما می توانید Rules خود را به همان اندازه که برای برنامه شما منطقی است، خاص یا عمومی کنید. قوانین Realtime Database از نحوی استفاده می کنند که شبیه جاوا اسکریپت در ساختار JSON است. قواعد Cloud Firestore و Cloud Storage از زبانی مبتنی بر Common Expression Language (CEL) استفاده می‌کنند که بر روی CEL با match ایجاد می‌کند و به عباراتی allow که از دسترسی مشروط اعطا شده پشتیبانی می‌کنند.

از آنجایی که این زبان‌ها زبان‌های سفارشی هستند، اما منحنی یادگیری وجود دارد. از این راهنما برای درک بهتر زبان Rules استفاده کنید، زیرا در قوانین پیچیده‌تر عمیق‌تر می‌شوید.

یک محصول را انتخاب کنید تا در مورد قوانین آن بیشتر بدانید.

ساختار اساسی

Cloud Firestore

Firebase Security Rules در Cloud Firestore و Cloud Storage از ساختار و نحو زیر استفاده می کنند:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

مفاهیم کلیدی زیر هنگام ایجاد قوانین برای درک مهم هستند:

  • Request: متد یا متدهای فراخوانی شده در دستور allow . اینها روشهایی هستند که شما به آنها اجازه اجرا می دهید. روش های استاندارد عبارتند از: get ، list ، create ، update و delete . روش‌های راحت read و write ، دسترسی گسترده خواندن و نوشتن را در پایگاه داده یا مسیر ذخیره‌سازی مشخص شده امکان‌پذیر می‌سازد.
  • Path: پایگاه داده یا محل ذخیره سازی که به عنوان یک مسیر URI نشان داده می شود.
  • قانون: عبارت allow ، که شامل شرطی است که در صورت ارزیابی صحیح، به درخواست اجازه می دهد.

هر یک از این مفاهیم در ادامه با جزئیات بیشتر توضیح داده شده است.

Cloud Storage

Firebase Security Rules در Cloud Firestore و Cloud Storage از ساختار و نحو زیر استفاده می کنند:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

مفاهیم کلیدی زیر هنگام ایجاد قوانین برای درک مهم هستند:

  • Request: متد یا متدهای فراخوانی شده در دستور allow . اینها روشهایی هستند که شما به آنها اجازه اجرا می دهید. روش های استاندارد عبارتند از: get ، list ، create ، update و delete . روش‌های راحت read و write ، دسترسی گسترده خواندن و نوشتن را در پایگاه داده یا مسیر ذخیره‌سازی مشخص شده امکان‌پذیر می‌سازد.
  • Path: پایگاه داده یا محل ذخیره سازی که به عنوان یک مسیر URI نشان داده می شود.
  • قانون: عبارت allow ، که شامل شرطی است که در صورت ارزیابی صحیح، به درخواست اجازه می دهد.

هر یک از این مفاهیم در ادامه با جزئیات بیشتر توضیح داده شده است.

Realtime Database

در Realtime Database ، Firebase Security Rules از عبارات جاوا اسکریپت مانند موجود در یک سند JSON تشکیل شده است.

آنها از نحو زیر استفاده می کنند:

{
  "rules": {
    "<<path>>": {
    // Allow the request if the condition for each method is true.
      ".read": <<condition>>,
      ".write": <<condition>>,
      ".validate": <<condition>>
    }
  }
}

سه عنصر اساسی در قانون وجود دارد:

  • مسیر: محل پایگاه داده. این ساختار JSON پایگاه داده شما را منعکس می کند.
  • درخواست: اینها روش هایی هستند که قانون برای اعطای دسترسی استفاده می کند. قوانین read و write ، دسترسی خواندن و نوشتن گسترده ای را اعطا می کنند، در حالی که قوانین validate به عنوان یک تأیید ثانویه برای اعطای دسترسی بر اساس داده های ورودی یا موجود عمل می کنند.
  • شرط: شرطی که به یک درخواست اجازه می دهد در صورتی که درست ارزیابی شود.

ساختارهای قانون

Cloud Firestore

عناصر اساسی یک قانون در Cloud Firestore و Cloud Storage به شرح زیر است:

  • اعلامیه service : محصول Firebase را که قوانین بر آن اعمال می شود، اعلام می کند.
  • بلوک match : مسیری را در پایگاه داده یا سطل ذخیره سازی که قوانین روی آن اعمال می شود، تعریف می کند.
  • عبارت allow : شرایطی را برای اعطای دسترسی فراهم می کند که بر اساس روش ها متمایز می شود. روش های پشتیبانی شده عبارتند از: get ، list ، create ، update ، delete ، و روش های آسان read و write .
  • اعلان های function اختیاری: امکان ترکیب و بسته بندی شرایط را برای استفاده در چندین قانون فراهم می کند.

این service حاوی یک یا چند بلوک match با دستورات allow که شرایطی را برای دسترسی به درخواست ها فراهم می کند. متغیرهای request و resource برای استفاده در شرایط قانون در دسترس هستند. زبان Firebase Security Rules نیز از اعلان‌های function پشتیبانی می‌کند.

نسخه نحوی

دستور syntax نشان دهنده نسخه زبان قوانین Firebase است که برای نوشتن منبع استفاده شده است. آخرین نسخه این زبان v2 است.

rules_version = '2';
service cloud.firestore {
...
}

اگر هیچ عبارت rules_version ارائه نشده باشد، قوانین شما با استفاده از موتور v1 ارزیابی خواهند شد.

خدمات

اعلامیه service مشخص می کند که قوانین شما در مورد کدام محصول یا خدمات Firebase اعمال می شود. شما فقط می توانید یک اعلان service در هر فایل منبع اضافه کنید.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Cloud Storage

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

اگر قوانینی را برای Cloud Firestore و Cloud Storage با استفاده از Firebase CLI تعریف می کنید، باید آنها را در فایل های جداگانه نگهداری کنید.

مطابقت دادن

یک بلوک match الگوی path را اعلام می‌کند که با مسیر عملیات درخواستی مطابقت دارد (مسیر request.path ورودی). بدنه match باید یک یا چند بلوک match تودرتو، عبارات allow یا اعلان function داشته باشد. مسیر در بلوک‌های match تودرتو نسبت به مسیر بلوک match والد است.

الگوی path یک نام دایرکتوری است که ممکن است متغییرها یا حروف عام باشد. الگوی path امکان تطابق بخش تک مسیری و بخش چند مسیری را فراهم می کند. هر متغیر محدود شده در یک path در محدوده match یا هر محدوده تودرتو که در آن path اعلام شده است قابل مشاهده است.

مطابقت با الگوی path ممکن است جزئی یا کامل باشد:

  • منطبقات جزئی: الگوی path پیشوندی از request.path است.
  • تطابق کامل: الگوی path با کل request.path مطابقت دارد.

هنگامی که یک تطابق کامل ایجاد می شود، قوانین درون بلوک ارزیابی می شوند. وقتی یک تطابق جزئی ایجاد می‌شود، قوانین match تودرتو آزمایش می‌شوند تا ببینند آیا path تودرتو تطابق را کامل می‌کند یا خیر.

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

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

همانطور که مثال بالا نشان می دهد، اعلان path از متغیرهای زیر پشتیبانی می کند:

  • علامت عام تک بخش: یک متغیر علامت عام در یک مسیر با قرار دادن یک متغیر در پرانتزهای فرفری اعلام می شود: {variable} . این متغیر در دستور match به عنوان یک string قابل دسترسی است.
  • عام بازگشتی: عام بازگشتی، یا چند بخش، بخش های مسیر متعدد را در یک مسیر یا زیر آن مطابقت می دهد. این علامت عام با همه مسیرهای زیر مکانی که آن را تنظیم کرده اید مطابقت دارد. می توانید آن را با افزودن رشته =** در انتهای متغیر بخش خود اعلام کنید: {variable=**} . این متغیر در دستور match به عنوان یک شی path قابل دسترسی است.

اجازه دهید

بلوک match حاوی یک یا چند عبارت allow . اینها قوانین واقعی شما هستند. می توانید قوانین allow را برای یک یا چند روش اعمال کنید. برای اینکه Cloud Firestore یا Cloud Storage برای اعطای هر درخواست دریافتی، شرایط یک عبارت allow را درست ارزیابی کند. همچنین می توانید عبارات allow را بدون شرط بنویسید، به عنوان مثال، allow read . با این حال، اگر دستور allow شامل یک شرط نباشد، همیشه درخواست آن متد را مجاز می‌کند.

اگر هر یک از قوانین allow برای روش برآورده شود، درخواست مجاز است. علاوه بر این، اگر یک قانون گسترده‌تر دسترسی را اعطا کند، Rules دسترسی را اعطا می‌کنند و هر قانون جزئی دیگری که ممکن است دسترسی را محدود کند نادیده می‌گیرد.

مثال زیر را در نظر بگیرید، جایی که هر کاربر می تواند هر یک از فایل های خود را بخواند یا حذف کند. یک قانون جزئی تر فقط در صورتی اجازه نوشتن را می دهد که کاربر درخواست کننده نوشتن مالک فایل باشد و فایل PNG باشد. کاربر می تواند هر فایلی را در مسیر فرعی حذف کند - حتی اگر PNG نباشد - زیرا قانون قبلی این امکان را می دهد.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth != null && request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
  }
}

روش

هر دستور allow شامل روشی است که به درخواست های ورودی از همان روش دسترسی می دهد.

روش نوع درخواست
روش های راحتی
read هر نوع درخواست خواندن
write هر نوع درخواست نوشتن
روش های استاندارد
get درخواست‌ها برای اسناد یا فایل‌های واحد را بخوانید
list درخواست‌های مربوط به پرسش‌ها و مجموعه‌ها را بخوانید
create اسناد یا فایل های جدید بنویسید
update در اسناد پایگاه داده موجود بنویسید یا ابرداده فایل را به روز کنید
delete داده ها را حذف کنید

نمی‌توانید روش‌های خواندن را در یک بلوک match یا روش‌های نوشتن متناقض در یک اعلان path همپوشانی کنید.

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

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all authenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth != null && request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth != null && request.auth.uid == "me";
    }
  }
}

تابع

همانطور که قوانین امنیتی شما پیچیده‌تر می‌شوند، ممکن است بخواهید مجموعه‌ای از شرایط را در توابعی بپیچید که بتوانید در سراسر مجموعه قوانین خود دوباره از آنها استفاده کنید. قوانین امنیتی از توابع سفارشی پشتیبانی می کنند. سینتکس توابع سفارشی کمی شبیه جاوا اسکریپت است، اما توابع قوانین امنیتی در یک زبان مخصوص دامنه نوشته شده اند که دارای محدودیت های مهمی است:

  • توابع می توانند تنها حاوی یک عبارت return باشند. آنها نمی توانند حاوی هیچ منطق اضافی باشند. به عنوان مثال، آنها نمی توانند حلقه ها را اجرا کنند یا خدمات خارجی را فراخوانی کنند.
  • توابع می توانند به طور خودکار به توابع و متغیرها از محدوده ای که در آن تعریف شده اند دسترسی داشته باشند. به عنوان مثال، یک تابع تعریف شده در محدوده service cloud.firestore به متغیر resource و توابع داخلی مانند get() و exists() دسترسی دارد.
  • توابع ممکن است توابع دیگر را فراخوانی کنند اما ممکن است تکرار نشوند. کل عمق پشته تماس به 20 محدود شده است.
  • در قوانین نسخه v2 ، توابع می توانند متغیرها را با استفاده از کلمه کلیدی let تعریف کنند. توابع می توانند حداکثر 10 اتصال let داشته باشند، اما باید با یک عبارت return پایان یابند.

یک تابع با کلمه کلیدی 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();
    }
  }
}

در اینجا مثالی است که آرگومان های تابع و تخصیص اجازه را نشان می دهد. عبارات انتساب باید با نیمه ویرگول از هم جدا شوند.

function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
  return isAuthor || isAdmin;
}

توجه داشته باشید که چگونه تخصیص isAdmin جستجوی مجموعه مدیران را اعمال می کند. برای ارزیابی تنبل بدون نیاز به جستجوهای غیر ضروری، از ماهیت اتصال کوتاه && (AND) و || استفاده کنید. (OR) مقایسه برای فراخوانی تابع دوم تنها در صورتی که isAuthor درست (برای مقایسه && ) یا نادرست (برای مقایسه || ) نشان داده شود.

function isAdmin(userId) {
  return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  // `||` is short-circuiting; isAdmin called only if isAuthor == false.
  return isAuthor || isAdmin(userId);
}

استفاده از توابع در قوانین امنیتی شما با افزایش پیچیدگی قوانین شما، آنها را قابل نگهداری تر می کند.

Cloud Storage

عناصر اساسی یک قانون در Cloud Firestore و Cloud Storage به شرح زیر است:

  • اعلامیه service : محصول Firebase را که قوانین بر آن اعمال می شود، اعلام می کند.
  • بلوک match : مسیری را در پایگاه داده یا سطل ذخیره سازی که قوانین روی آن اعمال می شود، تعریف می کند.
  • عبارت allow : شرایطی را برای اعطای دسترسی فراهم می کند که بر اساس روش ها متمایز می شود. روش های پشتیبانی شده عبارتند از: get ، list ، create ، update ، delete ، و روش های آسان read و write .
  • اعلان های function اختیاری: امکان ترکیب و بسته بندی شرایط را برای استفاده در چندین قانون فراهم می کند.

این service حاوی یک یا چند بلوک match با دستورات allow که شرایطی را برای دسترسی به درخواست ها فراهم می کند. متغیرهای request و resource برای استفاده در شرایط قانون در دسترس هستند. زبان Firebase Security Rules نیز از اعلان‌های function پشتیبانی می‌کند.

نسخه نحوی

دستور syntax نشان دهنده نسخه زبان قوانین Firebase است که برای نوشتن منبع استفاده شده است. آخرین نسخه این زبان v2 است.

rules_version = '2';
service cloud.firestore {
...
}

اگر هیچ عبارت rules_version ارائه نشده باشد، قوانین شما با استفاده از موتور v1 ارزیابی خواهند شد.

خدمات

اعلامیه service مشخص می کند که قوانین شما در مورد کدام محصول یا خدمات Firebase اعمال می شود. شما فقط می توانید یک اعلان service در هر فایل منبع اضافه کنید.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Cloud Storage

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

اگر قوانینی را برای Cloud Firestore و Cloud Storage با استفاده از Firebase CLI تعریف می کنید، باید آنها را در فایل های جداگانه نگهداری کنید.

مطابقت دادن

یک بلوک match الگوی path را اعلام می‌کند که با مسیر عملیات درخواستی مطابقت دارد (مسیر request.path ورودی). بدنه match باید یک یا چند بلوک match تودرتو، عبارات allow یا اعلان function داشته باشد. مسیر در بلوک‌های match تودرتو نسبت به مسیر بلوک match والد است.

الگوی path یک نام دایرکتوری است که ممکن است متغییرها یا حروف عام باشد. الگوی path امکان تطابق بخش تک مسیری و بخش چند مسیری را فراهم می کند. هر متغیر محدود شده در یک path در محدوده match یا هر محدوده تودرتو که در آن path اعلام شده است قابل مشاهده است.

مطابقت با الگوی path ممکن است جزئی یا کامل باشد:

  • منطبقات جزئی: الگوی path پیشوندی از request.path است.
  • تطابق کامل: الگوی path با کل request.path مطابقت دارد.

هنگامی که یک تطابق کامل ایجاد می شود، قوانین درون بلوک ارزیابی می شوند. وقتی یک تطابق جزئی ایجاد می‌شود، قوانین match تودرتو آزمایش می‌شوند تا ببینند آیا path تودرتو تطابق را کامل می‌کند یا خیر.

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

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

همانطور که مثال بالا نشان می دهد، اعلان path از متغیرهای زیر پشتیبانی می کند:

  • علامت عام تک بخش: یک متغیر علامت عام در یک مسیر با قرار دادن یک متغیر در پرانتزهای فرفری اعلام می شود: {variable} . این متغیر در دستور match به عنوان یک string قابل دسترسی است.
  • عام بازگشتی: عام بازگشتی، یا چند بخش، بخش های مسیر متعدد را در یک مسیر یا زیر آن مطابقت می دهد. این علامت عام با همه مسیرهای زیر مکانی که آن را تنظیم کرده اید مطابقت دارد. می توانید آن را با افزودن رشته =** در انتهای متغیر بخش خود اعلام کنید: {variable=**} . این متغیر در دستور match به عنوان یک شی path قابل دسترسی است.

اجازه دهید

بلوک match حاوی یک یا چند عبارت allow . اینها قوانین واقعی شما هستند. می توانید قوانین allow را برای یک یا چند روش اعمال کنید. برای اینکه Cloud Firestore یا Cloud Storage برای اعطای هر درخواست دریافتی، شرایط یک عبارت allow را درست ارزیابی کند. همچنین می توانید عبارات allow را بدون شرط بنویسید، به عنوان مثال، allow read . با این حال، اگر دستور allow شامل یک شرط نباشد، همیشه درخواست آن متد را مجاز می‌کند.

اگر هر یک از قوانین allow برای روش برآورده شود، درخواست مجاز است. به‌علاوه، اگر قانون گسترده‌تری اجازه دسترسی را بدهد، Rules دسترسی را اعطا می‌کنند و هر قانون جزئی دیگری را که ممکن است دسترسی را محدود کند نادیده می‌گیرد.

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

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth != null && request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
  }
}

روش

هر دستور allow شامل روشی است که به درخواست های ورودی همان روش دسترسی می دهد.

روش نوع درخواست
روش های راحتی
read هر نوع درخواست خواندن
write هر نوع درخواست نوشتن
روش های استاندارد
get درخواست‌ها برای اسناد یا فایل‌های واحد را بخوانید
list درخواست‌های مربوط به پرسش‌ها و مجموعه‌ها را بخوانید
create اسناد یا فایل های جدید بنویسید
update در اسناد پایگاه داده موجود بنویسید یا ابرداده فایل را به روز کنید
delete داده ها را حذف کنید

نمی‌توانید روش‌های خواندن را در یک بلوک match یا روش‌های نوشتن متناقض در یک اعلان path همپوشانی کنید.

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

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all authenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth != null && request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth != null && request.auth.uid == "me";
    }
  }
}

تابع

همانطور که قوانین امنیتی شما پیچیده‌تر می‌شوند، ممکن است بخواهید مجموعه‌ای از شرایط را در توابعی بپیچید که بتوانید در سراسر مجموعه قوانین خود دوباره از آنها استفاده کنید. قوانین امنیتی از توابع سفارشی پشتیبانی می کنند. سینتکس توابع سفارشی کمی شبیه جاوا اسکریپت است، اما توابع قوانین امنیتی در یک زبان مخصوص دامنه نوشته شده اند که دارای محدودیت های مهمی است:

  • توابع می توانند تنها حاوی یک عبارت return باشند. آنها نمی توانند حاوی هیچ منطق اضافی باشند. به عنوان مثال، آنها نمی توانند حلقه ها را اجرا کنند یا خدمات خارجی را فراخوانی کنند.
  • توابع می توانند به طور خودکار به توابع و متغیرها از محدوده ای که در آن تعریف شده اند دسترسی داشته باشند. به عنوان مثال، یک تابع تعریف شده در محدوده service cloud.firestore به متغیر resource و توابع داخلی مانند get() و exists() دسترسی دارد.
  • توابع ممکن است توابع دیگر را فراخوانی کنند اما ممکن است تکرار نشوند. کل عمق پشته تماس به 20 محدود شده است.
  • در قوانین نسخه v2 ، توابع می توانند متغیرها را با استفاده از کلمه کلیدی let تعریف کنند. توابع می توانند حداکثر 10 اتصال let داشته باشند، اما باید با یک عبارت return پایان یابند.

یک تابع با کلمه کلیدی 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();
    }
  }
}

در اینجا مثالی است که آرگومان های تابع و تخصیص اجازه را نشان می دهد. اجازه دهید دستورات تکلیف باید با نیمه ویرگول از هم جدا شوند.

function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
  return isAuthor || isAdmin;
}

توجه داشته باشید که چگونه تخصیص isAdmin جستجوی مجموعه مدیران را اعمال می کند. برای ارزیابی تنبل بدون نیاز به جستجوهای غیر ضروری، از ماهیت اتصال کوتاه && (AND) و || استفاده کنید. (OR) مقایسه برای فراخوانی تابع دوم تنها در صورتی که isAuthor درست (برای مقایسه && ) یا نادرست (برای مقایسه || ) نشان داده شود.

function isAdmin(userId) {
  return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  // `||` is short-circuiting; isAdmin called only if isAuthor == false.
  return isAuthor || isAdmin(userId);
}

استفاده از توابع در قوانین امنیتی شما با افزایش پیچیدگی قوانین شما، آنها را قابل نگهداری تر می کند.

Realtime Database

همانطور که در بالا ذکر شد، Rules Realtime Database شامل سه عنصر اساسی است: مکان پایگاه داده به عنوان آینه ساختار JSON پایگاه داده، نوع درخواست، و شرایط اعطای دسترسی.

مکان پایگاه داده

ساختار قوانین شما باید از ساختار داده هایی که در پایگاه داده خود ذخیره کرده اید پیروی کند. به عنوان مثال، در یک برنامه چت با لیستی از پیام‌ها، ممکن است داده‌هایی به شکل زیر داشته باشید:

  {
    "messages": {
      "message0": {
        "content": "Hello",
        "timestamp": 1405704370369
      },
      "message1": {
        "content": "Goodbye",
        "timestamp": 1405704395231
      },
      ...
    }
  }

قوانین شما باید آن ساختار را منعکس کند. به عنوان مثال:

  {
    "rules": {
      "messages": {
        "$message": {
          // only messages from the last ten minutes can be read
          ".read": "data.child('timestamp').val() > (now - 600000)",

          // new messages must have a string content and a number timestamp
          ".validate": "newData.hasChildren(['content', 'timestamp']) &&
                        newData.child('content').isString() &&
                        newData.child('timestamp').isNumber()"
        }
      }
    }
  }

همانطور که مثال بالا نشان می دهد، Rules Realtime Database از یک متغیر $location برای مطابقت با بخش های مسیر پشتیبانی می کنند. از پیشوند $ در جلوی بخش مسیر خود استفاده کنید تا قانون خود را با گره های فرزند در طول مسیر مطابقت دهید.

  {
    "rules": {
      "rooms": {
        // This rule applies to any child of /rooms/, the key for each room id
        // is stored inside $room_id variable for reference
        "$room_id": {
          "topic": {
            // The room's topic can be changed if the room id has "public" in it
            ".write": "$room_id.contains('public')"
          }
        }
      }
    }
  }

همچنین می توانید از $variable به صورت موازی با نام مسیرهای ثابت استفاده کنید.

  {
    "rules": {
      "widget": {
        // a widget can have a title or color attribute
        "title": { ".validate": true },
        "color": { ".validate": true },

        // but no other child paths are allowed
        // in this case, $other means any key excluding "title" and "color"
        "$other": { ".validate": false }
      }
    }
  }

روش

در Realtime Database ، سه نوع قانون وجود دارد. دو نوع از این قوانین - read و write - در روش درخواست ورودی اعمال می شود. نوع قانون validate ساختارهای داده را اعمال می کند و قالب و محتوای داده ها را تأیید می کند. Rules پس از تأیید اینکه یک قانون .write اجازه دسترسی می دهد، قوانین .validate اجرا می کنند.

انواع قوانین
.خواندن توضیح می دهد که آیا و چه زمانی داده ها مجاز به خواندن توسط کاربران هستند.
.نوشتن توضیح می دهد که آیا و چه زمانی داده ها مجاز به نوشتن هستند.
اعتبار سنجی تعیین می کند که یک مقدار به درستی قالب بندی شده چگونه به نظر می رسد، آیا دارای ویژگی های فرزند و نوع داده است.

به طور پیش‌فرض، اگر قانونی وجود نداشته باشد، دسترسی به یک مسیر رد می‌شود.

شرایط ساختمان

Cloud Firestore

شرط یک عبارت بولی است که تعیین می کند آیا یک عملیات خاص باید مجاز یا رد شود. متغیرهای request و resource زمینه را برای آن شرایط فراهم می کنند.

متغیر request

متغیر request شامل فیلدهای زیر و اطلاعات مربوطه است:

request.auth

یک رمز وب JSON (JWT) که حاوی اعتبارنامه های احراز هویت از Firebase Authentication است. نشانه auth شامل مجموعه‌ای از ادعاهای استاندارد و هرگونه ادعای سفارشی است که از طریق Firebase Authentication ایجاد می‌کنید. درباره Firebase Security Rules و Authentication بیشتر بیاموزید.

request.method

روش request.method ممکن است یکی از روش های استاندارد یا یک روش سفارشی باشد. روش‌های راحت read و write نیز برای ساده کردن قوانین نوشتن وجود دارد که به ترتیب برای همه روش‌های استاندارد فقط خواندنی یا فقط نوشتنی اعمال می‌شوند.

request.params

request.params شامل هر داده ای است که به طور خاص به request.resource مربوط نمی شود و ممکن است برای ارزیابی مفید باشد. در عمل، این نقشه باید برای همه روش‌های استاندارد خالی باشد و باید حاوی داده‌های غیرمنبعی برای روش‌های سفارشی باشد. سرویس‌ها باید مراقب باشند که هیچ یک از کلیدها و مقادیر ارائه شده به عنوان پارامترها را تغییر نام یا تغییر ندهند.

request.path

request.path مسیر resource هدف است. مسیر نسبت به سرویس است. بخش‌های مسیر حاوی نویسه‌های غیر url ایمن مانند / با URL کدگذاری می‌شوند.

متغیر resource

resource مقدار فعلی در سرویس است که به صورت نقشه جفت های کلید-مقدار نمایش داده می شود. ارجاع resource در یک شرط منجر به حداکثر یک خواندن مقدار از سرویس می شود. این جستجو در هر سهمیه مربوط به خدمات برای منبع حساب می شود. برای get درخواست‌ها، resource فقط برای رد کردن سهمیه حساب می‌کند.

اپراتورها و تقدم عملگر

از جدول زیر به عنوان مرجع برای اپراتورها و اولویت مربوط به آنها در Rules برای Cloud Firestore و Cloud Storage استفاده کنید.

عبارات دلخواه a و b ، یک فیلد f و یک شاخص i داده می شود.

اپراتور توضیحات انجمنی
a[i] a() af فهرست، تماس، دسترسی به میدان چپ به راست
!a -a نفی واحد راست به چپ
a/ba%ba*b عملگرهای ضربی چپ به راست
a+b ab اپراتورهای افزودنی چپ به راست
a>ba>=ba عملگرهای رابطه ای چپ به راست
a in b وجود در فهرست یا نقشه چپ به راست
a is type مقایسه نوع، که در آن type می تواند bool، int، float، عدد، رشته، لیست، نقشه، مهر زمانی، مدت زمان، مسیر یا latlng باشد. چپ به راست
a==ba!=b عملگرهای مقایسه چپ به راست
a && b AND مشروط چپ به راست
a || b OR مشروط چپ به راست
a ? true_value : false_value بیان سه تایی چپ به راست

Cloud Storage

شرط یک عبارت بولی است که تعیین می کند آیا یک عملیات خاص باید مجاز یا رد شود. متغیرهای request و resource زمینه را برای آن شرایط فراهم می کنند.

متغیر request

متغیر request شامل فیلدهای زیر و اطلاعات مربوطه است:

request.auth

یک رمز وب JSON (JWT) که حاوی اعتبارنامه های احراز هویت از Firebase Authentication است. نشانه auth شامل مجموعه‌ای از ادعاهای استاندارد و هرگونه ادعای سفارشی است که از طریق Firebase Authentication ایجاد می‌کنید. درباره Firebase Security Rules و Authentication بیشتر بیاموزید.

request.method

روش request.method ممکن است یکی از روش های استاندارد یا یک روش سفارشی باشد. روش‌های راحت read و write نیز برای ساده کردن قوانین نوشتن وجود دارد که به ترتیب برای همه روش‌های استاندارد فقط خواندنی یا فقط نوشتنی اعمال می‌شوند.

request.params

request.params شامل هر داده ای است که به طور خاص به request.resource مربوط نمی شود و ممکن است برای ارزیابی مفید باشد. در عمل، این نقشه باید برای همه روش‌های استاندارد خالی باشد و باید حاوی داده‌های غیرمنبعی برای روش‌های سفارشی باشد. سرویس‌ها باید مراقب باشند که هیچ یک از کلیدها و مقادیر ارائه شده به عنوان پارامترها را تغییر نام یا تغییر ندهند.

request.path

request.path مسیر resource هدف است. مسیر نسبت به سرویس است. بخش‌های مسیر حاوی نویسه‌های غیر url ایمن مانند / با URL کدگذاری می‌شوند.

متغیر resource

resource مقدار فعلی در سرویس است که به صورت نقشه جفت های کلید-مقدار نمایش داده می شود. ارجاع resource در یک شرط منجر به حداکثر یک خواندن مقدار از سرویس می شود. این جستجو در هر سهمیه مربوط به خدمات برای منبع حساب می شود. برای get درخواست‌ها، resource فقط برای رد کردن سهمیه حساب می‌کند.

اپراتورها و تقدم عملگر

از جدول زیر به عنوان مرجع برای اپراتورها و اولویت مربوط به آنها در Rules برای Cloud Firestore و Cloud Storage استفاده کنید.

عبارات دلخواه a و b ، یک فیلد f و یک شاخص i داده می شود.

اپراتور توضیحات انجمنی
a[i] a() af فهرست، تماس، دسترسی به میدان چپ به راست
!a -a نفی واحد راست به چپ
a/ba%ba*b عملگرهای ضربی چپ به راست
a+b ab اپراتورهای افزودنی چپ به راست
a>ba>=ba عملگرهای رابطه ای چپ به راست
a in b وجود در فهرست یا نقشه چپ به راست
a is type مقایسه نوع، که در آن type می تواند bool، int، float، عدد، رشته، لیست، نقشه، مهر زمانی، مدت زمان، مسیر یا latlng باشد. چپ به راست
a==ba!=b عملگرهای مقایسه چپ به راست
a && b AND مشروط چپ به راست
a || b OR مشروط چپ به راست
a ? true_value : false_value بیان سه تایی چپ به راست

Realtime Database

شرط یک عبارت بولی است که تعیین می کند آیا یک عملیات خاص باید مجاز یا رد شود. شما می توانید آن شرایط را در Rules Realtime Database به روش های زیر تعریف کنید.

متغیرهای از پیش تعریف شده

تعدادی متغیر مفید و از پیش تعریف شده وجود دارد که در داخل یک تعریف قانون می توان به آنها دسترسی داشت. در اینجا خلاصه ای از هر یک آمده است:

متغیرهای از پیش تعریف شده
اکنون زمان کنونی بر حسب میلی ثانیه از دوران لینوکس. این به ویژه برای اعتبارسنجی مهرهای زمانی ایجاد شده با firebase.database.ServerValue.TIMESTAMP SDK خوب عمل می کند.
ریشه یک RuleDataSnapshot نشان دهنده مسیر ریشه در پایگاه داده Firebase همانطور که قبل از عملیات تلاش شده وجود دارد.
داده های جدید یک RuleDataSnapshot که داده‌ها را به شکلی که پس از عملیات تلاش شده وجود دارد، نشان می‌دهد. این شامل داده های جدید نوشته شده و داده های موجود است.
داده ها یک RuleDataSnapshot که داده‌ها را به‌صورتی که قبل از عملیات انجام شده وجود داشت نشان می‌دهد.
متغیرهای $ یک مسیر عام که برای نمایش شناسه ها و کلیدهای فرزند پویا استفاده می شود.
اعتبار نشان دهنده بار توکن کاربر تأیید شده است.

این متغیرها در هر جایی از قوانین شما قابل استفاده هستند. به عنوان مثال، قوانین امنیتی زیر تضمین می کند که داده های نوشته شده در گره /foo/ باید رشته ای کمتر از 100 کاراکتر باشد:

{
  "rules": {
    "foo": {
      // /foo is readable by the world
      ".read": true,

      // /foo is writable by the world
      ".write": true,

      // data written to /foo must be a string less than 100 characters
      ".validate": "newData.isString() && newData.val().length < 100"
    }
  }
}

قوانین مبتنی بر داده

هر داده ای در پایگاه داده شما می تواند در قوانین شما استفاده شود. با استفاده از متغیرهای از پیش تعریف شده root ، data و newData ، می توانید به هر مسیری که قبل یا بعد از یک رویداد نوشتن وجود دارد دسترسی داشته باشید.

این مثال را در نظر بگیرید، که تا زمانی که مقدار گره /allow_writes/ true است، عملیات نوشتن اجازه می دهد، گره والد یک مجموعه پرچم readOnly ندارد و فرزندی به نام foo در داده های جدید نوشته شده وجود دارد:

".write": "root.child('allow_writes').val() === true &&
          !data.parent().child('readOnly').exists() &&
          newData.child('foo').exists()"

قوانین مبتنی بر پرس و جو

اگرچه نمی توانید از قوانین به عنوان فیلتر استفاده کنید، اما می توانید با استفاده از پارامترهای پرس و جو در قوانین خود دسترسی به زیر مجموعه های داده را محدود کنید. از query. استفاده کنید عباراتی در قوانین شما برای اعطای دسترسی خواندن یا نوشتن بر اساس پارامترهای پرس و جو.

به عنوان مثال، قانون مبتنی بر پرس و جو زیر از قوانین امنیتی مبتنی بر کاربر و قوانین مبتنی بر پرس و جو استفاده می کند تا دسترسی به داده های مجموعه baskets را فقط به سبدهای خریدی که کاربر فعال دارد محدود کند:

"baskets": {
  ".read": "auth.uid !== null &&
            query.orderByChild === 'owner' &&
            query.equalTo === auth.uid" // restrict basket access to owner of basket
}

پرس و جو زیر که شامل پارامترهای پرس و جو در قانون است، موفق خواهد بود:

db.ref("baskets").orderByChild("owner")
                 .equalTo(auth.currentUser.uid)
                 .on("value", cb)                 // Would succeed

با این حال، پرس و جوهایی که پارامترهای قانون را شامل نمی شوند با خطای PermissionDenied شکست می خورند:

db.ref("baskets").on("value", cb)                 // Would fail with PermissionDenied

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

به عنوان مثال، قانون زیر دسترسی خواندن را به 1000 نتیجه اول یک پرس و جو، طبق اولویت، محدود می کند:

messages: {
  ".read": "query.orderByKey &&
            query.limitToFirst <= 1000"
}

// Example queries:

db.ref("messages").on("value", cb)                // Would fail with PermissionDenied

db.ref("messages").limitToFirst(1000)
                  .on("value", cb)                // Would succeed (default order by key)

query. عبارات در Realtime Database Security Rules در دسترس هستند.

عبارات قانون مبتنی بر پرس و جو
بیان تایپ کنید توضیحات
query.orderByKey
query.orderByPriority
query.orderByValue
بولی درست برای جستارهای مرتب شده بر اساس کلید، اولویت یا مقدار. در غیر این صورت نادرست است.
query.orderByChild رشته
تهی
از یک رشته برای نشان دادن مسیر نسبی به یک گره فرزند استفاده کنید. برای مثال query.orderByChild === "address/zip" . اگر پرس و جو توسط یک گره فرزند مرتب نشده باشد، این مقدار null است.
query.startAt
query.endAt
query.equalTo
رشته
شماره
بولی
تهی
محدوده‌های کوئری اجرا را بازیابی می‌کند، یا اگر مجموعه‌ای محدود وجود نداشته باشد، null را برمی‌گرداند.
query.limitToFirst
query.limitToLast
شماره
تهی
محدودیت پرس و جو در حال اجرا را بازیابی می کند یا اگر محدودیتی تنظیم نشده باشد، null را برمی گرداند.

اپراتورها

Rules Realtime Database از تعدادی عملگر پشتیبانی می کند که می توانید از آنها برای ترکیب متغیرها در عبارت شرط استفاده کنید. لیست کامل اپراتورها را در مستندات مرجع مشاهده کنید.

ایجاد شرایط

شرایط واقعی شما بر اساس دسترسی‌هایی که می‌خواهید اعطا کنید، متفاوت خواهد بود. Rules به طور عمدی درجه بسیار زیادی از انعطاف پذیری را ارائه می دهند، بنابراین قوانین برنامه شما می توانند در نهایت به همان اندازه که شما نیاز دارید ساده یا پیچیده باشند.

برای راهنمایی در مورد ایجاد Rules ساده و آماده برای تولید، به قوانین اساسی امنیت مراجعه کنید.

،

Firebase Security Rules از زبان‌های منعطف، قدرتمند و سفارشی استفاده می‌کند که از طیف وسیعی از پیچیدگی و جزئیات پشتیبانی می‌کنند. شما می توانید Rules خود را به همان اندازه که برای برنامه شما منطقی است، خاص یا عمومی کنید. قوانین Realtime Database از نحوی استفاده می کنند که شبیه جاوا اسکریپت در ساختار JSON است. قواعد Cloud Firestore و Cloud Storage از زبانی مبتنی بر Common Expression Language (CEL) استفاده می‌کنند که بر روی CEL با match ایجاد می‌کند و به عباراتی allow که از دسترسی مشروط اعطا شده پشتیبانی می‌کنند.

از آنجایی که این زبان‌ها زبان‌های سفارشی هستند، اما منحنی یادگیری وجود دارد. از این راهنما برای درک بهتر زبان Rules استفاده کنید، زیرا در قوانین پیچیده‌تر عمیق‌تر می‌شوید.

یک محصول را انتخاب کنید تا در مورد قوانین آن بیشتر بدانید.

ساختار اساسی

Cloud Firestore

Firebase Security Rules در Cloud Firestore و Cloud Storage از ساختار و نحو زیر استفاده می کنند:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

مفاهیم کلیدی زیر هنگام ایجاد قوانین برای درک مهم هستند:

  • Request: متد یا متدهای فراخوانی شده در دستور allow . اینها روشهایی هستند که شما به آنها اجازه اجرا می دهید. روش های استاندارد عبارتند از: get ، list ، create ، update و delete . روش‌های راحت read و write ، دسترسی گسترده خواندن و نوشتن را در پایگاه داده یا مسیر ذخیره‌سازی مشخص شده امکان‌پذیر می‌سازد.
  • Path: پایگاه داده یا محل ذخیره سازی که به عنوان یک مسیر URI نشان داده می شود.
  • قانون: عبارت allow ، که شامل شرطی است که در صورت ارزیابی صحیح، به درخواست اجازه می دهد.

هر یک از این مفاهیم در ادامه با جزئیات بیشتر توضیح داده شده است.

Cloud Storage

Firebase Security Rules در Cloud Firestore و Cloud Storage از ساختار و نحو زیر استفاده می کنند:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

درک مفاهیم کلیدی زیر هنگام ایجاد قوانین مهم است:

  • Request: متد یا متدهای فراخوانی شده در دستور allow . اینها روشهایی هستند که شما به آنها اجازه اجرا می دهید. روش های استاندارد عبارتند از: get ، list ، create ، update و delete . روش‌های راحت read و write ، دسترسی گسترده خواندن و نوشتن را در پایگاه داده یا مسیر ذخیره‌سازی مشخص شده امکان‌پذیر می‌سازد.
  • Path: پایگاه داده یا محل ذخیره سازی که به عنوان یک مسیر URI نشان داده می شود.
  • قانون: عبارت allow ، که شامل شرطی است که در صورت ارزیابی صحیح، به درخواست اجازه می دهد.

هر یک از این مفاهیم در ادامه با جزئیات بیشتر توضیح داده شده است.

Realtime Database

در Realtime Database ، Firebase Security Rules از عبارات جاوا اسکریپت مانند موجود در یک سند JSON تشکیل شده است.

آنها از نحو زیر استفاده می کنند:

{
  "rules": {
    "<<path>>": {
    // Allow the request if the condition for each method is true.
      ".read": <<condition>>,
      ".write": <<condition>>,
      ".validate": <<condition>>
    }
  }
}

سه عنصر اساسی در قانون وجود دارد:

  • مسیر: محل پایگاه داده. این ساختار JSON پایگاه داده شما را منعکس می کند.
  • درخواست: اینها روش هایی هستند که قانون برای اعطای دسترسی استفاده می کند. قوانین read و write ، دسترسی خواندن و نوشتن گسترده ای را اعطا می کنند، در حالی که قوانین validate به عنوان یک تأیید ثانویه برای اعطای دسترسی بر اساس داده های ورودی یا موجود عمل می کنند.
  • شرط: شرطی که به یک درخواست اجازه می دهد در صورتی که درست ارزیابی شود.

ساختارهای قانون

Cloud Firestore

عناصر اساسی یک قانون در Cloud Firestore و Cloud Storage به شرح زیر است:

  • اعلامیه service : محصول Firebase را که قوانین بر آن اعمال می شود، اعلام می کند.
  • بلوک match : مسیری را در پایگاه داده یا سطل ذخیره سازی که قوانین روی آن اعمال می شود، تعریف می کند.
  • عبارت allow : شرایطی را برای اعطای دسترسی فراهم می کند که بر اساس روش ها متمایز می شود. روش های پشتیبانی شده عبارتند از: get ، list ، create ، update ، delete ، و روش های آسان read و write .
  • اعلان های function اختیاری: امکان ترکیب و بسته بندی شرایط را برای استفاده در چندین قانون فراهم می کند.

این service حاوی یک یا چند بلوک match با دستورات allow که شرایطی را برای دسترسی به درخواست ها فراهم می کند. متغیرهای request و resource برای استفاده در شرایط قانون در دسترس هستند. زبان Firebase Security Rules نیز از اعلان‌های function پشتیبانی می‌کند.

نسخه نحوی

دستور syntax نشان دهنده نسخه زبان قوانین Firebase است که برای نوشتن منبع استفاده شده است. آخرین نسخه این زبان v2 است.

rules_version = '2';
service cloud.firestore {
...
}

اگر هیچ عبارت rules_version ارائه نشده باشد، قوانین شما با استفاده از موتور v1 ارزیابی خواهند شد.

خدمات

اعلامیه service مشخص می کند که قوانین شما در مورد کدام محصول یا خدمات Firebase اعمال می شود. شما فقط می توانید یک اعلان service در هر فایل منبع اضافه کنید.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Cloud Storage

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

اگر قوانینی را برای Cloud Firestore و Cloud Storage با استفاده از Firebase CLI تعریف می کنید، باید آنها را در فایل های جداگانه نگهداری کنید.

مطابقت دادن

یک بلوک match الگوی path را اعلام می‌کند که با مسیر عملیات درخواستی مطابقت دارد (مسیر request.path ورودی). بدنه match باید یک یا چند بلوک match تودرتو، عبارات allow یا اعلان function داشته باشد. مسیر در بلوک‌های match تودرتو نسبت به مسیر بلوک match والد است.

الگوی path یک نام دایرکتوری است که ممکن است متغییرها یا حروف عام باشد. الگوی path امکان تطابق بخش تک مسیری و بخش چند مسیری را فراهم می کند. هر متغیر محدود شده در یک path در محدوده match یا هر محدوده تودرتو که در آن path اعلام شده است قابل مشاهده است.

مطابقت با الگوی path ممکن است جزئی یا کامل باشد:

  • منطبقات جزئی: الگوی path پیشوندی از request.path است.
  • تطابق کامل: الگوی path با کل request.path مطابقت دارد.

هنگامی که یک تطابق کامل ایجاد می شود، قوانین درون بلوک ارزیابی می شوند. وقتی یک تطابق جزئی ایجاد می‌شود، قوانین match تودرتو آزمایش می‌شوند تا ببینند آیا path تودرتو تطابق را کامل می‌کند یا خیر.

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

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

همانطور که مثال بالا نشان می دهد، اعلان path از متغیرهای زیر پشتیبانی می کند:

  • علامت عام تک بخش: یک متغیر علامت عام در یک مسیر با قرار دادن یک متغیر در پرانتزهای فرفری اعلام می شود: {variable} . این متغیر در دستور match به عنوان یک string قابل دسترسی است.
  • عام بازگشتی: عام بازگشتی، یا چند بخش، بخش های مسیر متعدد را در یک مسیر یا زیر آن مطابقت می دهد. این علامت عام با همه مسیرهای زیر مکانی که آن را تنظیم کرده اید مطابقت دارد. می توانید با اضافه کردن رشته =** در انتهای متغیر بخش خود ، آن را اعلام کنید: {variable=**} . این متغیر در عبارت match به عنوان یک شیء path قابل دسترسی است.

اجازه دهید

بلوک match شامل یک یا چند جمله allow . این قوانین واقعی شماست. می توانید قوانین را برای یک یا چند روش allow کنید. شرایط موجود در یک بیانیه allow باید برای صدور Cloud Firestore یا Cloud Storage برای اعطای هرگونه درخواست ورودی ، ارزیابی شود. همچنین می توانید بیانیه های allow را بدون شرط بنویسید ، به عنوان مثال ، allow read . اگر بیانیه allow یک شرط را در بر نگیرد ، با این حال ، همیشه درخواست آن روش را می دهد.

اگر هر یک از قوانین allow برای این روش راضی باشد ، درخواست مجاز است. علاوه بر این ، اگر یک قانون گسترده تر دسترسی به آنها را اعطا کند ، Rules به دسترسی اعطا می شوند و هرگونه قانون دانه ای را که ممکن است دسترسی را محدود کند ، نادیده می گیرد.

مثال زیر را در نظر بگیرید ، جایی که هر کاربر می تواند هر یک از پرونده های خود را بخواند یا حذف کند. یک قانون گرانول تر فقط در صورتی که کاربر درخواست نوشتن پرونده را در اختیار داشته باشد ، می نویسد و پرونده PNG است. یک کاربر می تواند هر پرونده ای را در زیر آب - حتی اگر PNG نباشد - حذف کند زیرا قانون قبلی اجازه می دهد.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth != null && request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
  }
}

روش

هر عبارت allow شامل روشی است که دسترسی به درخواست های ورودی با همان روش را اعطا می کند.

روش نوع درخواست
روشهای راحتی
read هر نوع درخواست خواندن
write هر نوع درخواست نوشتن
روشهای استاندارد
get درخواست های اسناد یا پرونده های منفرد را بخوانید
list درخواست های پرس و جو و مجموعه ها را بخوانید
create اسناد یا پرونده های جدید را بنویسید
update در اسناد پایگاه داده موجود بنویسید یا ابرداده پرونده را به روز کنید
delete داده ها را حذف کنید

شما نمی توانید روش های خواندن را در همان بلوک match یا روش های نوشتن متضاد در همان اعلامیه path همپوشانی کنید.

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

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all authenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth != null && request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth != null && request.auth.uid == "me";
    }
  }
}

تابع

هرچه قوانین امنیتی شما پیچیده تر می شوند ، ممکن است بخواهید مجموعه ای از شرایط را در کارکردهایی ببندید که می توانید از آنها در قوانین خود استفاده مجدد کنید. قوانین امنیتی از عملکردهای سفارشی پشتیبانی می کنند. نحو برای توابع سفارشی کمی شبیه JavaScript است ، اما توابع قوانین امنیتی به زبانی خاص دامنه نوشته شده است که محدودیت های مهمی دارد:

  • توابع فقط می توانند حاوی یک عبارت return واحد باشند. آنها نمی توانند حاوی منطق اضافی باشند. به عنوان مثال ، آنها نمی توانند حلقه ها را اجرا کنند یا با خدمات خارجی تماس بگیرند.
  • توابع می توانند به طور خودکار به توابع و متغیرها از محدوده تعریف شده در آنها دسترسی پیدا کنند. به عنوان مثال ، یک تابع تعریف شده در service cloud.firestore Scope به متغیر resource و توابع داخلی مانند get() و exists() .
  • توابع ممکن است کارکردهای دیگر را فراخوانی کنند اما ممکن است مجدداً مورد استفاده قرار نگیرند. کل عمق پشته تماس محدود به 20 است.
  • در قوانین نسخه 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();
    }
  }
}

در اینجا مثالی آورده شده است که آرگومان های عملکرد را نشان می دهد و به تکالیف اجازه می دهد. بگذارید اظهارات واگذاری باید توسط نیمه کلون ها از هم جدا شوند.

function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
  return isAuthor || isAdmin;
}

توجه داشته باشید که چگونه تکلیف isAdmin به جستجوی مجموعه Admins می پردازد. برای ارزیابی تنبل بدون نیاز به جستجوی غیر ضروری ، از ماهیت اتصال کوتاه && (و) و || استفاده کنید (یا) مقایسه برای تماس با یک عملکرد دوم فقط در صورتی که isAuthor صحیح باشد (برای مقایسه && مقایسه) یا کاذب (برای || مقایسه).

function isAdmin(userId) {
  return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  // `||` is short-circuiting; isAdmin called only if isAuthor == false.
  return isAuthor || isAdmin(userId);
}

استفاده از توابع در قوانین امنیتی شما با افزایش پیچیدگی قوانین شما ، آنها را حفظ می کند.

Cloud Storage

عناصر اساسی یک قاعده در Cloud Firestore و Cloud Storage به شرح زیر است:

  • بیانیه service : محصول Firebase را که قوانین مربوط به آن اعمال می شود اعلام می کند.
  • Block match : مسیری را در پایگاه داده یا سطل ذخیره سازی تعریف می کند که قوانین مربوط به آن است.
  • بیانیه allow : شرایط لازم برای اعطای دسترسی ، متمایز با روش ها را فراهم می کند. روشهای پشتیبانی شده عبارتند از: get ، list ، create ، update ، delete و روشهای راحتی read و write .
  • اعلامیه های function اختیاری: امکان ترکیب و بسته بندی شرایط برای استفاده در چندین قوانین را فراهم می کند.

این service شامل یک یا چند بلوک match با اظهارات allow که شرایط دسترسی به درخواست ها را فراهم می کند. متغیرهای request و resource برای استفاده در شرایط قانون در دسترس هستند. زبان Firebase Security Rules همچنین از اعلامیه های function پشتیبانی می کند.

نسخه نحو

بیانیه syntax نسخه زبان قوانین Firebase را برای نوشتن منبع نشان می دهد. آخرین نسخه زبان v2 است.

rules_version = '2';
service cloud.firestore {
...
}

در صورت عدم ارائه بیانیه rules_version ، قوانین شما با استفاده از موتور v1 ارزیابی می شود.

خدمات

بیانیه service مشخص می کند که کدام محصول Firebase یا خدمات ، قوانین شما اعمال می شود. شما فقط می توانید در هر پرونده منبع یک اعلامیه service را درج کنید.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Cloud Storage

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

اگر با استفاده از CLI Firebase ، قوانینی را برای Cloud Firestore و Cloud Storage تعریف می کنید ، باید آنها را در پرونده های جداگانه حفظ کنید.

مطابقت دادن

یک بلوک match یک الگوی path را اعلام می کند که در برابر مسیر عملیات درخواست شده مطابقت دارد ( request.path ). بدنه match باید یک یا چند بلوک match تو در تو داشته باشد ، اظهارات یا اعلامیه های function را allow . مسیر بلوک های match تو در تو نسبت به مسیر در بلوک match والدین است.

الگوی path نامی شبیه به فهرست است که ممکن است شامل متغیرها یا کارتهای وحشی باشد. الگوی path اجازه می دهد تا بخش تک مسیر و مسابقات چند مسیر را انجام دهد. هر متغیر محدود در یک path در محدوده match یا هر محدوده تو در تو که در path اعلام شده است قابل مشاهده است.

مطابقت با الگوی path ممکن است جزئی یا کامل باشد:

  • مسابقات جزئی: الگوی path یک پیشوند مسابقه از request.path است. PATH.
  • مسابقات کامل: الگوی path با کل request.path مطابقت دارد.

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

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

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

همانطور که نمونه بالا نشان می دهد ، اعلامیه های path از متغیرهای زیر پشتیبانی می کنند:

  • کارت وحشی تک بخش: یک متغیر کارت وحشی در یک مسیر با بسته بندی یک متغیر در بریس های مجعد اعلام می شود: {variable} . این متغیر در عبارت match به عنوان یک string قابل دسترسی است.
  • Wildcard Renursive: Wildcard بازگشتی ، یا چند بخش ، با بخش های مختلف مسیر در مسیر یا زیر یک مسیر مطابقت دارد. این کارت وحشی با تمام مسیرهای زیر مکانی که آن را تنظیم کرده اید مطابقت دارد. می توانید با اضافه کردن رشته =** در انتهای متغیر بخش خود ، آن را اعلام کنید: {variable=**} . این متغیر در عبارت match به عنوان یک شیء path قابل دسترسی است.

اجازه دهید

بلوک match شامل یک یا چند جمله allow . این قوانین واقعی شماست. می توانید قوانین را برای یک یا چند روش allow کنید. شرایط موجود در یک بیانیه allow باید برای صدور Cloud Firestore یا Cloud Storage برای اعطای هرگونه درخواست ورودی ، ارزیابی شود. همچنین می توانید بیانیه های allow را بدون شرط بنویسید ، به عنوان مثال ، allow read . اگر بیانیه allow یک شرط را در بر نگیرد ، با این حال ، همیشه درخواست آن روش را می دهد.

اگر هر یک از قوانین allow برای این روش راضی باشد ، درخواست مجاز است. علاوه بر این ، اگر یک قانون گسترده تر دسترسی به آنها را اعطا کند ، Rules به دسترسی اعطا می شوند و هرگونه قانون دانه ای را که ممکن است دسترسی را محدود کند ، نادیده می گیرد.

مثال زیر را در نظر بگیرید ، جایی که هر کاربر می تواند هر یک از پرونده های خود را بخواند یا حذف کند. یک قانون گرانول تر فقط در صورتی که کاربر درخواست نوشتن پرونده را در اختیار داشته باشد ، می نویسد و پرونده PNG است. یک کاربر می تواند هر پرونده ای را در زیر آب - حتی اگر PNG نباشد - حذف کند زیرا قانون قبلی اجازه می دهد.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth != null && request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
  }
}

روش

هر عبارت allow شامل روشی است که دسترسی به درخواست های ورودی با همان روش را اعطا می کند.

روش نوع درخواست
روشهای راحتی
read هر نوع درخواست خواندن
write هر نوع درخواست نوشتن
روشهای استاندارد
get درخواست های اسناد یا پرونده های منفرد را بخوانید
list درخواست های پرس و جو و مجموعه ها را بخوانید
create اسناد یا پرونده های جدید را بنویسید
update در اسناد پایگاه داده موجود بنویسید یا ابرداده پرونده را به روز کنید
delete داده ها را حذف کنید

شما نمی توانید روش های خواندن را در همان بلوک match یا روش های نوشتن متضاد در همان اعلامیه path همپوشانی کنید.

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

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all authenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth != null && request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth != null && request.auth.uid == "me";
    }
  }
}

تابع

هرچه قوانین امنیتی شما پیچیده تر می شوند ، ممکن است بخواهید مجموعه ای از شرایط را در کارکردهایی ببندید که می توانید از آنها در قوانین خود استفاده مجدد کنید. قوانین امنیتی از عملکردهای سفارشی پشتیبانی می کنند. نحو برای توابع سفارشی کمی شبیه JavaScript است ، اما توابع قوانین امنیتی به زبانی خاص دامنه نوشته شده است که محدودیت های مهمی دارد:

  • توابع فقط می توانند حاوی یک عبارت return واحد باشند. آنها نمی توانند حاوی منطق اضافی باشند. به عنوان مثال ، آنها نمی توانند حلقه ها را اجرا کنند یا با خدمات خارجی تماس بگیرند.
  • توابع می توانند به طور خودکار به توابع و متغیرها از محدوده تعریف شده در آنها دسترسی پیدا کنند. به عنوان مثال ، یک تابع تعریف شده در service cloud.firestore Scope به متغیر resource و توابع داخلی مانند get() و exists() .
  • توابع ممکن است کارکردهای دیگر را فراخوانی کنند اما ممکن است مجدداً مورد استفاده قرار نگیرند. کل عمق پشته تماس محدود به 20 است.
  • در قوانین نسخه 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();
    }
  }
}

در اینجا مثالی آورده شده است که آرگومان های عملکرد را نشان می دهد و به تکالیف اجازه می دهد. بگذارید اظهارات واگذاری باید توسط نیمه کلون ها از هم جدا شوند.

function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
  return isAuthor || isAdmin;
}

توجه داشته باشید که چگونه تکلیف isAdmin به جستجوی مجموعه Admins می پردازد. برای ارزیابی تنبل بدون نیاز به جستجوی غیر ضروری ، از ماهیت اتصال کوتاه && (و) و || استفاده کنید (یا) مقایسه برای تماس با یک عملکرد دوم فقط در صورتی که isAuthor صحیح باشد (برای مقایسه && مقایسه) یا کاذب (برای || مقایسه).

function isAdmin(userId) {
  return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  // `||` is short-circuiting; isAdmin called only if isAuthor == false.
  return isAuthor || isAdmin(userId);
}

استفاده از توابع در قوانین امنیتی شما با افزایش پیچیدگی قوانین شما ، آنها را حفظ می کند.

Realtime Database

همانطور که در بالا ذکر شد ، Rules Realtime Database شامل سه عنصر اساسی است: مکان پایگاه داده به عنوان آینه ای از ساختار JSON پایگاه داده ، نوع درخواست و شرط دسترسی به آن.

محل پایگاه داده

ساختار قوانین شما باید ساختار داده هایی را که در پایگاه داده خود ذخیره کرده اید دنبال کنید. به عنوان مثال ، در یک برنامه گپ با لیستی از پیام ها ، ممکن است داده هایی داشته باشید که به نظر می رسد:

  {
    "messages": {
      "message0": {
        "content": "Hello",
        "timestamp": 1405704370369
      },
      "message1": {
        "content": "Goodbye",
        "timestamp": 1405704395231
      },
      ...
    }
  }

قوانین شما باید آن ساختار را آینه دهد. به عنوان مثال:

  {
    "rules": {
      "messages": {
        "$message": {
          // only messages from the last ten minutes can be read
          ".read": "data.child('timestamp').val() > (now - 600000)",

          // new messages must have a string content and a number timestamp
          ".validate": "newData.hasChildren(['content', 'timestamp']) &&
                        newData.child('content').isString() &&
                        newData.child('timestamp').isNumber()"
        }
      }
    }
  }

همانطور که در مثال بالا نشان داده شده است ، Rules Realtime Database از یک متغیر $location برای مطابقت با بخش های مسیر پشتیبانی می کنند. از پیشوند $ در مقابل بخش مسیر خود استفاده کنید تا قانون خود را با هر گره کودک در طول مسیر مطابقت دهید.

  {
    "rules": {
      "rooms": {
        // This rule applies to any child of /rooms/, the key for each room id
        // is stored inside $room_id variable for reference
        "$room_id": {
          "topic": {
            // The room's topic can be changed if the room id has "public" in it
            ".write": "$room_id.contains('public')"
          }
        }
      }
    }
  }

همچنین می توانید از $variable به موازات نام مسیر ثابت استفاده کنید.

  {
    "rules": {
      "widget": {
        // a widget can have a title or color attribute
        "title": { ".validate": true },
        "color": { ".validate": true },

        // but no other child paths are allowed
        // in this case, $other means any key excluding "title" and "color"
        "$other": { ".validate": false }
      }
    }
  }

روش

در Realtime Database ، سه نوع قانون وجود دارد. دو مورد از این نوع قانون - read و write - به روش درخواست ورودی اعمال می شود. نوع قانون validate ، ساختار داده ها را اجرا می کند و قالب و محتوای داده ها را تأیید می کند. Rules اجرا می شوند .validate قوانین را پس از تأیید اینکه یک قانون .write دسترسی را اعطا می کند ، ارزیابی می کند.

انواع قانون
.خواندن توصیف می کند که آیا و چه زمانی داده ها توسط کاربران خوانده می شوند.
. نوشتن توصیف می کند که آیا و چه زمانی داده ها نوشته شده است.
.تامدین کردن تعریف می کند که یک مقدار به درستی فرمت شده به نظر می رسد ، چه ویژگی های کودک را داشته باشد و نوع داده.

به طور پیش فرض ، اگر قانونی برای اجازه دادن به آن وجود نداشته باشد ، دسترسی در یک مسیر رد می شود.

شرایط ساختمانی

Cloud Firestore

یک شرط یک عبارت بولی است که تعیین می کند که آیا یک عمل خاص باید مجاز باشد یا انکار شود. متغیرهای request و resource زمینه ای را برای آن شرایط فراهم می کنند.

متغیر request

متغیر request شامل قسمتهای زیر و اطلاعات مربوطه است:

request.auth

یک توکن وب JSON (JWT) که حاوی اعتبار تأیید اعتبار از Firebase Authentication است. Token auth شامل مجموعه ای از ادعاهای استاندارد و هرگونه ادعای سفارشی است که شما از طریق Firebase Authentication ایجاد می کنید. در مورد Firebase Security Rules و Authentication بیشتر بدانید.

request.method

request.method . method ممکن است هر یک از روش های استاندارد یا یک روش سفارشی باشد. روشهای راحتی read و write برای ساده تر کردن قوانین نوشتن که به ترتیب برای کلیه روشهای استاندارد فقط خواندنی یا فقط نوشتن اعمال می شود.

request.params

request.params شامل هر داده ای است که به طور خاص به request.resource که ممکن است برای ارزیابی مفید باشد. در عمل ، این نقشه باید برای همه روشهای استاندارد خالی باشد و باید برای روشهای سفارشی دارای داده های غیر منابع باشد. خدمات باید مراقب باشند که نوع و مقادیر ارائه شده به عنوان پارامترها را تغییر نام یا اصلاح نکنند.

request.path

request.path مسیر resource هدف است. مسیر نسبت به سرویس است. بخش های مسیر حاوی شخصیت های ایمن غیر URL مانند / رمزگذاری شده URL.

متغیر resource

resource مقدار فعلی در سرویس است که به عنوان نقشه جفت های ارزش کلید نشان داده شده است. مراجعه به resource در یک شرط حداکثر یک خواندن مقدار از سرویس را به همراه خواهد داشت. این جستجوی در برابر هر سهمیه مربوط به خدمات برای این منبع حساب خواهد شد. برای درخواست های get ، این resource فقط به سهمیه در مورد انکار حساب می شود.

برتری اپراتورها و اپراتور

از جدول زیر به عنوان مرجع برای اپراتورها و تقدم مربوط به آنها در Rules مربوط به Cloud Firestore و Cloud Storage استفاده کنید.

با توجه به عبارات دلخواه a و b ، یک زمینه f و یک فهرست i

اپراتور توضیحات انجمنی
a[i] a() af فهرست ، تماس ، دسترسی به زمینه چپ به راست
!a -a نفی ادغام راست به چپ
a/ba%ba*b اپراتورهای چند برابر چپ به راست
a+b ab اپراتورهای افزودنی چپ به راست
a>ba>=ba عملگرهای رابطه ای چپ به راست
a in b وجود در لیست یا نقشه چپ به راست
a is type مقایسه نوع ، که در آن type می تواند BOOL ، INT ، FLOAT ، شماره ، لیست ، لیست ، نقشه ، Timestamp ، مدت زمان ، مسیر یا latlng باشد چپ به راست
a==ba!=b عملگرهای مقایسه چپ به راست
a && b مشروط چپ به راست
a || b مشروط یا چپ به راست
a ? true_value : false_value بیان سه گانه چپ به راست

Cloud Storage

یک شرط یک عبارت بولی است که تعیین می کند که آیا یک عمل خاص باید مجاز باشد یا انکار شود. متغیرهای request و resource زمینه ای را برای آن شرایط فراهم می کنند.

متغیر request

متغیر request شامل قسمتهای زیر و اطلاعات مربوطه است:

request.auth

یک توکن وب JSON (JWT) که حاوی اعتبار تأیید اعتبار از Firebase Authentication است. Token auth شامل مجموعه ای از ادعاهای استاندارد و هرگونه ادعای سفارشی است که شما از طریق Firebase Authentication ایجاد می کنید. در مورد Firebase Security Rules و Authentication بیشتر بدانید.

request.method

request.method . method ممکن است هر یک از روش های استاندارد یا یک روش سفارشی باشد. روشهای راحتی read و write برای ساده تر کردن قوانین نوشتن که به ترتیب برای کلیه روشهای استاندارد فقط خواندنی یا فقط نوشتن اعمال می شود.

request.params

request.params شامل هر داده ای است که به طور خاص به request.resource که ممکن است برای ارزیابی مفید باشد. در عمل ، این نقشه باید برای همه روشهای استاندارد خالی باشد و باید برای روشهای سفارشی دارای داده های غیر منابع باشد. خدمات باید مراقب باشند که نوع و مقادیر ارائه شده به عنوان پارامترها را تغییر نام یا اصلاح نکنند.

request.path

request.path مسیر resource هدف است. مسیر نسبت به سرویس است. بخش های مسیر حاوی شخصیت های ایمن غیر URL مانند / رمزگذاری شده URL.

متغیر resource

resource مقدار فعلی در سرویس است که به عنوان نقشه جفت های ارزش کلید نشان داده شده است. مراجعه به resource در یک شرط حداکثر یک خواندن مقدار از سرویس را به همراه خواهد داشت. این جستجوی در برابر هر سهمیه مربوط به خدمات برای این منبع حساب خواهد شد. برای درخواست های get ، این resource فقط به سهمیه در مورد انکار حساب می شود.

برتری اپراتورها و اپراتور

از جدول زیر به عنوان مرجع برای اپراتورها و تقدم مربوط به آنها در Rules مربوط به Cloud Firestore و Cloud Storage استفاده کنید.

با توجه به عبارات دلخواه a و b ، یک زمینه f و یک فهرست i

اپراتور توضیحات انجمنی
a[i] a() af فهرست ، تماس ، دسترسی به زمینه چپ به راست
!a -a نفی ادغام راست به چپ
a/ba%ba*b اپراتورهای چند برابر چپ به راست
a+b ab اپراتورهای افزودنی چپ به راست
a>ba>=ba عملگرهای رابطه ای چپ به راست
a in b وجود در لیست یا نقشه چپ به راست
a is type مقایسه نوع ، که در آن type می تواند BOOL ، INT ، FLOAT ، شماره ، لیست ، لیست ، نقشه ، Timestamp ، مدت زمان ، مسیر یا latlng باشد چپ به راست
a==ba!=b عملگرهای مقایسه چپ به راست
a && b مشروط چپ به راست
a || b مشروط یا چپ به راست
a ? true_value : false_value بیان سه گانه چپ به راست

Realtime Database

یک شرط یک عبارت بولی است که تعیین می کند که آیا یک عمل خاص باید مجاز باشد یا انکار شود. می توانید آن شرایط را در Rules Realtime Database به روش های زیر تعریف کنید.

متغیرهای از پیش تعریف شده

تعدادی از متغیرهای مفید و از پیش تعریف شده وجود دارد که می توانند در یک تعریف قانون به آنها دسترسی پیدا کنند. در اینجا خلاصه ای از هر یک آورده شده است:

متغیرهای از پیش تعریف شده
اکنون زمان فعلی در میلی ثانیه از زمان لینوکس. این به ویژه برای اعتبار سنجی زمانی ایجاد شده با Firebase.database.servervalue.timestamp SDK خوب کار می کند.
ریشه یک Ruledatasnapshot که نشان دهنده مسیر ریشه در پایگاه داده Firebase است ، همانطور که قبل از تلاش برای عملیات وجود دارد.
نیوداتا یک Ruledatasnapshot نشان دهنده داده ها پس از انجام عملیات وجود دارد. این شامل داده های جدید نوشته شده و داده های موجود است.
داده ها یک حاکمیتسناپچوت نشان دهنده داده ها همانطور که قبل از عملیات وجود داشته است.
متغیرهای $ یک مسیر کارت وحشی برای نشان دادن شناسه ها و کلیدهای پویا کودک استفاده می شود.
اعتبار نمایانگر بار توکن کاربر معتبر است.

این متغیرها را می توان در هر نقطه از قوانین شما استفاده کرد. به عنوان مثال ، قوانین امنیتی زیر اطمینان می دهد که داده های نوشته شده به /foo/ node باید رشته ای کمتر از 100 کاراکتر باشد:

{
  "rules": {
    "foo": {
      // /foo is readable by the world
      ".read": true,

      // /foo is writable by the world
      ".write": true,

      // data written to /foo must be a string less than 100 characters
      ".validate": "newData.isString() && newData.val().length < 100"
    }
  }
}

قوانین مبتنی بر داده ها

هرگونه داده ای در پایگاه داده شما می تواند در قوانین شما استفاده شود. با استفاده از root ، data و newData از متغیرهای از پیش تعریف شده ، می توانید به هر مسیری دسترسی پیدا کنید که قبل یا بعد از یک رویداد نوشتن وجود داشته باشد.

این مثال را در نظر بگیرید ، که اجازه می دهد تا عملیات نوشتن را تا زمانی که مقدار /allow_writes/ گره true باشد ، گره والدین یک مجموعه پرچم readOnly ندارد ، و در داده های تازه نوشته شده کودکی به نام foo وجود دارد:

".write": "root.child('allow_writes').val() === true &&
          !data.parent().child('readOnly').exists() &&
          newData.child('foo').exists()"

قوانین مبتنی بر پرس و جو

اگرچه شما نمی توانید از قوانین به عنوان فیلترها استفاده کنید ، می توانید با استفاده از پارامترهای پرس و جو در قوانین خود ، دسترسی به زیر مجموعه های داده را محدود کنید. از query. عبارات در قوانین خود برای اعطای دسترسی به خواندن یا نوشتن بر اساس پارامترهای پرس و جو.

به عنوان مثال ، قانون مبتنی بر پرس و جو زیر از قوانین امنیتی مبتنی بر کاربر و قوانین مبتنی بر پرس و جو برای محدود کردن دسترسی به داده ها در مجموعه baskets فقط به سبد های خرید کاربر فعال استفاده می کند:

"baskets": {
  ".read": "auth.uid !== null &&
            query.orderByChild === 'owner' &&
            query.equalTo === auth.uid" // restrict basket access to owner of basket
}

پرس و جو زیر ، که شامل پارامترهای پرس و جو در قانون است ، موفق می شود:

db.ref("baskets").orderByChild("owner")
                 .equalTo(auth.currentUser.uid)
                 .on("value", cb)                 // Would succeed

با این حال ، نمایش داده شدگان که شامل پارامترهای موجود در این قاعده نمی شود با یک خطای PermissionDenied شکست می خورد:

db.ref("baskets").on("value", cb)                 // Would fail with PermissionDenied

همچنین می توانید از قوانین مبتنی بر پرس و جو استفاده کنید تا میزان بارگیری مشتری از طریق عملیات خوانده شده را محدود کنید.

به عنوان مثال ، قانون زیر محدودیت دسترسی به تنها 1000 نتیجه اول پرس و جو را می خواند ، همانطور که از اولویت سفارش داده شده است:

messages: {
  ".read": "query.orderByKey &&
            query.limitToFirst <= 1000"
}

// Example queries:

db.ref("messages").on("value", cb)                // Would fail with PermissionDenied

db.ref("messages").limitToFirst(1000)
                  .on("value", cb)                // Would succeed (default order by key)

query. زیر عبارات در Realtime Database Security Rules در دسترس هستند.

عبارات قاعده مبتنی بر پرس و جو
بیان تایپ کنید توضیحات
query.orderbykey
query.orderbypriority
query.orderbyValue
بولی درست برای نمایش داده شدگان سفارش داده شده توسط کلید ، اولویت یا ارزش. در غیر این صورت نادرست است.
query.orderbychild رشته
تهی
از یک رشته برای نشان دادن مسیر نسبی گره کودک استفاده کنید. به عنوان مثال ، query.orderByChild === "address/zip" . اگر پرس و جو توسط گره کودک سفارش داده نشود ، این مقدار تهی است.
query.startat
query.endat
پرس و جو.
رشته
شماره
بولی
تهی
مرزهای پرس و جو اعدام را بازیابی می کند ، یا در صورت عدم وجود مجموعه محدود ، تهی را برمی گرداند.
query.limittofirst
query.limittolast
شماره
تهی
در صورت عدم وجود محدودیت ، محدودیت در پرس و جو را بازیابی می کند ، یا در صورت عدم وجود محدودیت ، تهی را باز می گرداند.

اپراتورها

Rules Realtime Database از تعدادی از اپراتورهایی که می توانید از آنها برای ترکیب متغیرها در بیانیه شرط استفاده کنید ، پشتیبانی می کند. لیست کامل اپراتورها را در مستندات مرجع مشاهده کنید.

ایجاد شرایط

شرایط واقعی شما بر اساس دسترسی که می خواهید اعطا کنید متفاوت خواهد بود. Rules عمداً میزان انعطاف پذیری عظیمی را ارائه می دهند ، بنابراین قوانین برنامه شما در نهایت می تواند به همان اندازه ساده یا پیچیده باشد که به آنها نیاز دارید.

برای برخی از راهنمایی ها ایجاد Rules ساده و آماده تولید ، به قوانین اساسی امنیتی مراجعه کنید.

،

Firebase Security Rules زبانهای انعطاف پذیر ، قدرتمند و سفارشی را پشتیبانی می کند که از طیف گسترده ای از پیچیدگی و دانه بندی پشتیبانی می کند. شما می توانید Rules خود را به همان اندازه خاص یا عمومی تنظیم کنید که برای برنامه شما معنی دارد. قوانین Realtime Database از نحو استفاده می کنند که مانند JavaScript در یک ساختار JSON است. Firestore Cloud Firestore و Cloud Storage از یک زبان مبتنی بر زبان بیان مشترک (CEL) استفاده می کنند ، که بر روی CEL با match ساخته می شود و اظهاراتی را که از دسترسی مشروط پشتیبانی می کنند allow .

از آنجا که این زبان های سفارشی هستند ، با این حال ، یک منحنی یادگیری وجود دارد. از این راهنما برای درک بهتر زبان Rules استفاده کنید ، زیرا عمیق تر به قوانین پیچیده تر شیرجه می شوید.

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

ساختار اساسی

Cloud Firestore

Firebase Security Rules در Cloud Firestore و Cloud Storage از ساختار و نحو زیر استفاده می کنند:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

مفاهیم کلیدی زیر برای درک قوانین مهم هستند:

  • درخواست: روش یا روشهای فراخوانی شده در بیانیه allow . اینها روشهایی است که شما اجازه اجرای آن را دارید. روشهای استاندارد عبارتند از: get ، list ، create ، update و delete . روشهای راحتی read و write دسترسی گسترده به خواندن و نوشتن را در پایگاه داده یا مسیر ذخیره سازی مشخص می کند.
  • مسیر: پایگاه داده یا محل ذخیره سازی ، به عنوان یک مسیر URI نشان داده شده است.
  • قانون: بیانیه allow ، که شامل شرایطی است که در صورت ارزیابی صحیح ، درخواست را مجاز می کند.

هر یک از این مفاهیم در جزئیات بیشتر در زیر شرح داده شده است.

Cloud Storage

Firebase Security Rules در Cloud Firestore و Cloud Storage از ساختار و نحو زیر استفاده می کنند:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

مفاهیم کلیدی زیر برای درک قوانین مهم هستند:

  • درخواست: روش یا روشهای فراخوانی شده در بیانیه allow . اینها روشهایی است که شما اجازه اجرای آن را دارید. روشهای استاندارد عبارتند از: get ، list ، create ، update و delete . روشهای راحتی read و write دسترسی گسترده به خواندن و نوشتن را در پایگاه داده یا مسیر ذخیره سازی مشخص می کند.
  • مسیر: پایگاه داده یا محل ذخیره سازی ، به عنوان یک مسیر URI نشان داده شده است.
  • قانون: بیانیه allow ، که شامل شرایطی است که در صورت ارزیابی صحیح ، درخواست را مجاز می کند.

هر یک از این مفاهیم در جزئیات بیشتر در زیر شرح داده شده است.

Realtime Database

در Realtime Database ، Firebase Security Rules از عبارات مانند جاوا اسکریپت موجود در یک سند JSON تشکیل شده است.

آنها از نحو زیر استفاده می کنند:

{
  "rules": {
    "<<path>>": {
    // Allow the request if the condition for each method is true.
      ".read": <<condition>>,
      ".write": <<condition>>,
      ".validate": <<condition>>
    }
  }
}

سه عنصر اساسی در این قاعده وجود دارد:

  • مسیر: محل پایگاه داده. این ساختار JSON پایگاه داده شما را آینه می کند.
  • درخواست: این روشهایی است که قانون برای دسترسی به آنها استفاده می کند. قوانین read و write دسترسی گسترده ای را برای خواندن و نوشتن ارائه می دهد ، در حالی که قوانین validate به عنوان یک تأیید ثانویه برای اعطای دسترسی بر اساس داده های ورودی یا موجود عمل می کنند.
  • شرط: شرایطی که در صورت ارزیابی صحیح ، درخواست را مجاز می کند.

ساختار قانون

Cloud Firestore

عناصر اساسی یک قاعده در Cloud Firestore و Cloud Storage به شرح زیر است:

  • بیانیه service : محصول Firebase را که قوانین مربوط به آن اعمال می شود اعلام می کند.
  • Block match : مسیری را در پایگاه داده یا سطل ذخیره سازی تعریف می کند که قوانین مربوط به آن است.
  • بیانیه allow : شرایط لازم برای اعطای دسترسی ، متمایز با روش ها را فراهم می کند. روشهای پشتیبانی شده عبارتند از: get ، list ، create ، update ، delete و روشهای راحتی read و write .
  • اعلامیه های function اختیاری: امکان ترکیب و بسته بندی شرایط برای استفاده در چندین قوانین را فراهم می کند.

این service شامل یک یا چند بلوک match با اظهارات allow که شرایط دسترسی به درخواست ها را فراهم می کند. متغیرهای request و resource برای استفاده در شرایط قانون در دسترس هستند. زبان Firebase Security Rules همچنین از اعلامیه های function پشتیبانی می کند.

نسخه نحو

بیانیه syntax نسخه زبان قوانین Firebase را برای نوشتن منبع نشان می دهد. آخرین نسخه زبان v2 است.

rules_version = '2';
service cloud.firestore {
...
}

در صورت عدم ارائه بیانیه rules_version ، قوانین شما با استفاده از موتور v1 ارزیابی می شود.

خدمات

بیانیه service مشخص می کند که کدام محصول Firebase یا خدمات ، قوانین شما اعمال می شود. شما فقط می توانید در هر پرونده منبع یک اعلامیه service را درج کنید.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Cloud Storage

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

اگر با استفاده از CLI Firebase ، قوانینی را برای Cloud Firestore و Cloud Storage تعریف می کنید ، باید آنها را در پرونده های جداگانه حفظ کنید.

مطابقت دادن

یک بلوک match یک الگوی path را اعلام می کند که در برابر مسیر عملیات درخواست شده مطابقت دارد ( request.path ). بدنه match باید یک یا چند بلوک match تو در تو داشته باشد ، اظهارات یا اعلامیه های function را allow . مسیر بلوک های match تو در تو نسبت به مسیر در بلوک match والدین است.

الگوی path نامی شبیه به فهرست است که ممکن است شامل متغیرها یا کارتهای وحشی باشد. الگوی path اجازه می دهد تا بخش تک مسیر و مسابقات چند مسیر را انجام دهد. هر متغیر محدود در یک path در محدوده match یا هر محدوده تو در تو که در path اعلام شده است قابل مشاهده است.

مطابقت با الگوی path ممکن است جزئی یا کامل باشد:

  • مسابقات جزئی: الگوی path یک پیشوند مسابقه از request.path است. PATH.
  • مسابقات کامل: الگوی path با کل request.path مطابقت دارد.

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

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

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

همانطور که نمونه بالا نشان می دهد ، اعلامیه های path از متغیرهای زیر پشتیبانی می کنند:

  • کارت وحشی تک بخش: یک متغیر کارت وحشی در یک مسیر با بسته بندی یک متغیر در بریس های مجعد اعلام می شود: {variable} . این متغیر در عبارت match به عنوان یک string قابل دسترسی است.
  • Wildcard Renursive: Wildcard بازگشتی ، یا چند بخش ، با بخش های مختلف مسیر در مسیر یا زیر یک مسیر مطابقت دارد. این کارت وحشی با تمام مسیرهای زیر مکانی که آن را تنظیم کرده اید مطابقت دارد. می توانید با اضافه کردن رشته =** در انتهای متغیر بخش خود ، آن را اعلام کنید: {variable=**} . این متغیر در عبارت match به عنوان یک شیء path قابل دسترسی است.

اجازه دهید

بلوک match شامل یک یا چند جمله allow . این قوانین واقعی شماست. می توانید قوانین را برای یک یا چند روش allow کنید. شرایط موجود در یک بیانیه allow باید برای صدور Cloud Firestore یا Cloud Storage برای اعطای هرگونه درخواست ورودی ، ارزیابی شود. همچنین می توانید بیانیه های allow را بدون شرط بنویسید ، به عنوان مثال ، allow read . اگر بیانیه allow یک شرط را در بر نگیرد ، با این حال ، همیشه درخواست آن روش را می دهد.

اگر هر یک از قوانین allow برای این روش راضی باشد ، درخواست مجاز است. علاوه بر این ، اگر یک قانون گسترده تر دسترسی به آنها را اعطا کند ، Rules به دسترسی اعطا می شوند و هرگونه قانون دانه ای را که ممکن است دسترسی را محدود کند ، نادیده می گیرد.

مثال زیر را در نظر بگیرید ، جایی که هر کاربر می تواند هر یک از پرونده های خود را بخواند یا حذف کند. یک قانون گرانول تر فقط در صورتی که کاربر درخواست نوشتن پرونده را در اختیار داشته باشد ، می نویسد و پرونده PNG است. یک کاربر می تواند هر پرونده ای را در زیر آب - حتی اگر PNG نباشد - حذف کند زیرا قانون قبلی اجازه می دهد.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth != null && request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
  }
}

روش

هر عبارت allow شامل روشی است که دسترسی به درخواست های ورودی با همان روش را اعطا می کند.

روش نوع درخواست
روشهای راحتی
read هر نوع درخواست خواندن
write هر نوع درخواست نوشتن
روشهای استاندارد
get درخواست های اسناد یا پرونده های منفرد را بخوانید
list درخواست های پرس و جو و مجموعه ها را بخوانید
create اسناد یا پرونده های جدید را بنویسید
update در اسناد پایگاه داده موجود بنویسید یا ابرداده پرونده را به روز کنید
delete داده ها را حذف کنید

شما نمی توانید روش های خواندن را در همان بلوک match یا روش های نوشتن متضاد در همان اعلامیه path همپوشانی کنید.

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

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all authenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth != null && request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth != null && request.auth.uid == "me";
    }
  }
}

تابع

هرچه قوانین امنیتی شما پیچیده تر می شوند ، ممکن است بخواهید مجموعه ای از شرایط را در کارکردهایی ببندید که می توانید از آنها در قوانین خود استفاده مجدد کنید. قوانین امنیتی از عملکردهای سفارشی پشتیبانی می کنند. نحو برای توابع سفارشی کمی شبیه JavaScript است ، اما توابع قوانین امنیتی به زبانی خاص دامنه نوشته شده است که محدودیت های مهمی دارد:

  • توابع فقط می توانند حاوی یک عبارت return واحد باشند. آنها نمی توانند حاوی منطق اضافی باشند. به عنوان مثال ، آنها نمی توانند حلقه ها را اجرا کنند یا با خدمات خارجی تماس بگیرند.
  • توابع می توانند به طور خودکار به توابع و متغیرها از محدوده تعریف شده در آنها دسترسی پیدا کنند. به عنوان مثال ، یک تابع تعریف شده در service cloud.firestore Scope به متغیر resource و توابع داخلی مانند get() و exists() .
  • توابع ممکن است کارکردهای دیگر را فراخوانی کنند اما ممکن است مجدداً مورد استفاده قرار نگیرند. کل عمق پشته تماس محدود به 20 است.
  • در قوانین نسخه 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();
    }
  }
}

در اینجا مثالی آورده شده است که آرگومان های عملکرد را نشان می دهد و به تکالیف اجازه می دهد. بگذارید اظهارات واگذاری باید توسط نیمه کلون ها از هم جدا شوند.

function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
  return isAuthor || isAdmin;
}

توجه داشته باشید که چگونه تکلیف isAdmin به جستجوی مجموعه Admins می پردازد. برای ارزیابی تنبل بدون نیاز به جستجوی غیر ضروری ، از ماهیت اتصال کوتاه && (و) و || استفاده کنید (یا) مقایسه برای تماس با یک عملکرد دوم فقط در صورتی که isAuthor صحیح باشد (برای مقایسه && مقایسه) یا کاذب (برای || مقایسه).

function isAdmin(userId) {
  return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  // `||` is short-circuiting; isAdmin called only if isAuthor == false.
  return isAuthor || isAdmin(userId);
}

استفاده از توابع در قوانین امنیتی شما با افزایش پیچیدگی قوانین شما ، آنها را حفظ می کند.

Cloud Storage

عناصر اساسی یک قاعده در Cloud Firestore و Cloud Storage به شرح زیر است:

  • بیانیه service : محصول Firebase را که قوانین مربوط به آن اعمال می شود اعلام می کند.
  • Block match : مسیری را در پایگاه داده یا سطل ذخیره سازی تعریف می کند که قوانین مربوط به آن است.
  • بیانیه allow : شرایط لازم برای اعطای دسترسی ، متمایز با روش ها را فراهم می کند. روشهای پشتیبانی شده عبارتند از: get ، list ، create ، update ، delete و روشهای راحتی read و write .
  • اعلامیه های function اختیاری: امکان ترکیب و بسته بندی شرایط برای استفاده در چندین قوانین را فراهم می کند.

این service شامل یک یا چند بلوک match با اظهارات allow که شرایط دسترسی به درخواست ها را فراهم می کند. متغیرهای request و resource برای استفاده در شرایط قانون در دسترس هستند. زبان Firebase Security Rules همچنین از اعلامیه های function پشتیبانی می کند.

نسخه نحو

بیانیه syntax نسخه زبان قوانین Firebase را برای نوشتن منبع نشان می دهد. آخرین نسخه زبان v2 است.

rules_version = '2';
service cloud.firestore {
...
}

در صورت عدم ارائه بیانیه rules_version ، قوانین شما با استفاده از موتور v1 ارزیابی می شود.

خدمات

بیانیه service مشخص می کند که کدام محصول Firebase یا خدمات ، قوانین شما اعمال می شود. شما فقط می توانید در هر پرونده منبع یک اعلامیه service را درج کنید.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Cloud Storage

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

اگر با استفاده از CLI Firebase ، قوانینی را برای Cloud Firestore و Cloud Storage تعریف می کنید ، باید آنها را در پرونده های جداگانه حفظ کنید.

مطابقت دادن

یک بلوک match یک الگوی path را اعلام می کند که در برابر مسیر عملیات درخواست شده مطابقت دارد ( request.path ). بدنه match باید یک یا چند بلوک match تو در تو داشته باشد ، اظهارات یا اعلامیه های function را allow . مسیر بلوک های match تو در تو نسبت به مسیر در بلوک match والدین است.

الگوی path نامی شبیه به فهرست است که ممکن است شامل متغیرها یا کارتهای وحشی باشد. الگوی path اجازه می دهد تا بخش تک مسیر و مسابقات چند مسیر را انجام دهد. هر متغیر محدود در یک path در محدوده match یا هر محدوده تو در تو که در path اعلام شده است قابل مشاهده است.

مطابقت با الگوی path ممکن است جزئی یا کامل باشد:

  • مسابقات جزئی: الگوی path یک پیشوند مسابقه از request.path است. PATH.
  • مسابقات کامل: الگوی path با کل request.path مطابقت دارد.

هنگامی که یک مسابقه کامل انجام می شود ، قوانین موجود در بلوک ارزیابی می شوند. When a partial match is made the nested match rules are tested to see whether any nested path will complete the match.

The rules in each complete match are evaluated to determine whether to permit the request. If any matching rule grants access, the request is permitted. If no matching rule grants access, the request is denied.

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

As the example above shows, the path declarations supports the following variables:

  • Single-segment wildcard: A wildcard variable is declared in a path by wrapping a variable in curly braces: {variable} . This variable is accessible within the match statement as a string .
  • Recursive wildcard: The recursive, or multi-segment, wildcard matches multiple path segments at or below a path. This wildcard matches all paths below the location you set it to. You can declare it by adding the =** string at the end of your segment variable: {variable=**} . This variable is accessible within the match statement as a path object.

اجازه دهید

The match block contains one or more allow statements. These are your actual rules. You can apply allow rules to one or more methods. The conditions on an allow statement must evaluate to true for Cloud Firestore or Cloud Storage to grant any incoming request. You can also write allow statements without conditions, for example, allow read . If the allow statement doesn't include a condition, however, it always allows the request for that method.

If any of the allow rules for the method are satisfied, the request is allowed. Additionally, if a broader rule grants access, Rules grant access and ignore any more granular rules that might limit access.

Consider the following example, where any user can read or delete any of their own files. A more granular rule only allows writes if the user requesting the write owns the file and the file is a PNG. A user can delete any files at the subpath — even if they're not PNGs — because the earlier rule allows it.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth != null && request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
  }
}

روش

Each allow statement includes a method that grants access for incoming requests of the same method.

روش نوع درخواست
Convenience methods
read Any type of read request
write Any type of write request
Standard methods
get Read requests for single documents or files
list Read requests for queries and collections
create Write new documents or files
update Write to existing database documents or update file metadata
delete داده ها را حذف کنید

You can't overlap read methods in the same match block or conflicting write methods in the same path declaration.

For example, the following rules would fail:

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all authenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth != null && request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth != null && request.auth.uid == "me";
    }
  }
}

تابع

As your security rules become more complex, you may want to wrap sets of conditions in functions that you can reuse across your ruleset. Security rules support custom functions. The syntax for custom functions is a bit like JavaScript, but security rules functions are written in a domain-specific language that has some important limitations:

  • Functions can contain only a single return statement. They cannot contain any additional logic. For example, they cannot execute loops or call external services.
  • Functions can automatically access functions and variables from the scope in which they are defined. For example, a function defined within the service cloud.firestore scope has access to the resource variable and built-in functions such as get() and exists() .
  • Functions may call other functions but may not recurse. The total call stack depth is limited to 20.
  • In rules version v2 , functions can define variables using the let keyword. Functions can have up to 10 let bindings, but must end with a return statement.

A function is defined with the function keyword and takes zero or more arguments. For example, you may want to combine the two types of conditions used in the examples above into a single 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();
    }
  }
}

Here is an example showing function arguments and let assignments. Let assignment statements must be separated by semi-colons.

function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
  return isAuthor || isAdmin;
}

Note how the isAdmin assignment enforces a lookup of the admins collection. For lazy evaluation without requiring unneeded lookups, take advantage of the short-circuiting nature of && (AND) and || (OR) comparisons to call a second function only if isAuthor is shown to be true (for && comparisons) or false (for || comparisons).

function isAdmin(userId) {
  return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  // `||` is short-circuiting; isAdmin called only if isAuthor == false.
  return isAuthor || isAdmin(userId);
}

Using functions in your security rules makes them more maintainable as the complexity of your rules grows.

Realtime Database

As outlined above, Realtime Database Rules include three basic elements: the database location as a mirror of the database's JSON structure, the request type, and the condition granting access.

Database location

The structure of your rules should follow the structure of the data you have stored in your database. For example, in a chat app with a list of messages, you might have data that looks like this:

  {
    "messages": {
      "message0": {
        "content": "Hello",
        "timestamp": 1405704370369
      },
      "message1": {
        "content": "Goodbye",
        "timestamp": 1405704395231
      },
      ...
    }
  }

Your rules should mirror that structure. به عنوان مثال:

  {
    "rules": {
      "messages": {
        "$message": {
          // only messages from the last ten minutes can be read
          ".read": "data.child('timestamp').val() > (now - 600000)",

          // new messages must have a string content and a number timestamp
          ".validate": "newData.hasChildren(['content', 'timestamp']) &&
                        newData.child('content').isString() &&
                        newData.child('timestamp').isNumber()"
        }
      }
    }
  }

As the example above shows, Realtime Database Rules support a $location variable to match path segments. Use the $ prefix in front of your path segment to match your rule to any child nodes along the path.

  {
    "rules": {
      "rooms": {
        // This rule applies to any child of /rooms/, the key for each room id
        // is stored inside $room_id variable for reference
        "$room_id": {
          "topic": {
            // The room's topic can be changed if the room id has "public" in it
            ".write": "$room_id.contains('public')"
          }
        }
      }
    }
  }

You can also use the $variable in parallel with constant path names.

  {
    "rules": {
      "widget": {
        // a widget can have a title or color attribute
        "title": { ".validate": true },
        "color": { ".validate": true },

        // but no other child paths are allowed
        // in this case, $other means any key excluding "title" and "color"
        "$other": { ".validate": false }
      }
    }
  }

روش

In Realtime Database , there are three types of rules. Two of these rule types — read and write — apply to the method of an incoming request. The validate rule type enforces data structures and validates the format and content of data. Rules run .validate rules after verifying that a .write rule grants access.

Rule Types
.خواندن Describes if and when data is allowed to be read by users.
.write Describes if and when data is allowed to be written.
.validate Defines what a correctly formatted value will look like, whether it has child attributes, and the data type.

By default, if there isn't a rule allowing it, access at a path is denied.

Building conditions

Cloud Firestore

A condition is a boolean expression that determines whether a particular operation should be allowed or denied. The request and resource variables provide context for those conditions.

The request variable

The request variable includes the following fields and corresponding information:

request.auth

A JSON Web Token (JWT) that contains authentication credentials from Firebase Authentication . auth token contains a set of standard claims and any custom claims you create through Firebase Authentication . Learn more about Firebase Security Rules and Authentication .

request.method

The request.method may be any of the standard methods or a custom method. The convenience methods read and write also exist to simplify writing rules that apply to all read-only or all write-only standard methods respectively.

request.params

The request.params include any data not specifically related to the request.resource that might be useful for evaluation. In practice, this map should be empty for all standard methods, and should contain non-resource data for custom methods. Services must be careful not to rename or modify the type of any of the keys and values presented as params.

request.path

The request.path is the path for the target resource . The path is relative to the service. Path segments containing non-url safe characters such as / are url-encoded.

The resource variable

The resource is the current value within the service represented as a map of key-value pairs. Referencing resource within a condition will result in at most one read of the value from the service. This lookup will count against any service-related quota for the resource. For get requests, the resource will only count toward quota on deny.

Operators and operator precedence

Use the table below as a reference for operators and their corresponding precedence in Rules for Cloud Firestore and Cloud Storage .

Given arbitrary expressions a and b , a field f , and an index i .

اپراتور توضیحات انجمنی
a[i] a() af Index, call, field access left to right
!a -a Unary negation right to left
a/ba%ba*b Multiplicative operators left to right
a+b ab Additive operators left to right
a>ba>=ba عملگرهای رابطه ای left to right
a in b Existence in list or map left to right
a is type Type comparison, where type can be bool, int, float, number, string, list, map, timestamp, duration, path or latlng left to right
a==ba!=b عملگرهای مقایسه left to right
a && b Conditional AND left to right
a || b Conditional OR left to right
a ? true_value : false_value Ternary expression left to right

Cloud Storage

A condition is a boolean expression that determines whether a particular operation should be allowed or denied. The request and resource variables provide context for those conditions.

The request variable

The request variable includes the following fields and corresponding information:

request.auth

A JSON Web Token (JWT) that contains authentication credentials from Firebase Authentication . auth token contains a set of standard claims and any custom claims you create through Firebase Authentication . Learn more about Firebase Security Rules and Authentication .

request.method

The request.method may be any of the standard methods or a custom method. The convenience methods read and write also exist to simplify writing rules that apply to all read-only or all write-only standard methods respectively.

request.params

The request.params include any data not specifically related to the request.resource that might be useful for evaluation. In practice, this map should be empty for all standard methods, and should contain non-resource data for custom methods. Services must be careful not to rename or modify the type of any of the keys and values presented as params.

request.path

The request.path is the path for the target resource . The path is relative to the service. Path segments containing non-url safe characters such as / are url-encoded.

The resource variable

The resource is the current value within the service represented as a map of key-value pairs. Referencing resource within a condition will result in at most one read of the value from the service. This lookup will count against any service-related quota for the resource. For get requests, the resource will only count toward quota on deny.

Operators and operator precedence

Use the table below as a reference for operators and their corresponding precedence in Rules for Cloud Firestore and Cloud Storage .

Given arbitrary expressions a and b , a field f , and an index i .

اپراتور توضیحات انجمنی
a[i] a() af Index, call, field access left to right
!a -a Unary negation right to left
a/ba%ba*b Multiplicative operators left to right
a+b ab Additive operators left to right
a>ba>=ba عملگرهای رابطه ای left to right
a in b Existence in list or map left to right
a is type Type comparison, where type can be bool, int, float, number, string, list, map, timestamp, duration, path or latlng left to right
a==ba!=b عملگرهای مقایسه left to right
a && b Conditional AND left to right
a || b Conditional OR left to right
a ? true_value : false_value Ternary expression left to right

Realtime Database

A condition is a boolean expression that determines whether a particular operation should be allowed or denied. You can define those conditions in Realtime Database Rules in the following ways.

Pre-defined variables

There are a number of helpful, pre-defined variables that can be accessed inside a rule definition. Here is a brief summary of each:

Predefined Variables
اکنون The current time in milliseconds since Linux epoch. This works particularly well for validating timestamps created with the SDK's firebase.database.ServerValue.TIMESTAMP.
ریشه A RuleDataSnapshot representing the root path in the Firebase database as it exists before the attempted operation.
newData A RuleDataSnapshot representing the data as it would exist after the attempted operation. It includes the new data being written and existing data.
داده ها A RuleDataSnapshot representing the data as it existed before the attempted operation.
$ variables A wildcard path used to represent ids and dynamic child keys.
اعتبار Represents an authenticated user's token payload.

These variables can be used anywhere in your rules. For example, the security rules below ensure that data written to the /foo/ node must be a string less than 100 characters:

{
  "rules": {
    "foo": {
      // /foo is readable by the world
      ".read": true,

      // /foo is writable by the world
      ".write": true,

      // data written to /foo must be a string less than 100 characters
      ".validate": "newData.isString() && newData.val().length < 100"
    }
  }
}

Data-based rules

Any data in your database can be used in your rules. Using the predefined variables root , data , and newData , you can access any path as it would exist before or after a write event.

Consider this example, which allows write operations as long as the value of the /allow_writes/ node is true , the parent node does not have a readOnly flag set, and there is a child named foo in the newly written data:

".write": "root.child('allow_writes').val() === true &&
          !data.parent().child('readOnly').exists() &&
          newData.child('foo').exists()"

Query-based rules

Although you can't use rules as filters, you can limit access to subsets of data by using query parameters in your rules. Use query. expressions in your rules to grant read or write access based on query parameters.

For example, the following query-based rule uses user-based security rules and query-based rules to restrict access to data in the baskets collection to only the shopping baskets the active user owns:

"baskets": {
  ".read": "auth.uid !== null &&
            query.orderByChild === 'owner' &&
            query.equalTo === auth.uid" // restrict basket access to owner of basket
}

The following query, which includes the query parameters in the rule, would succeed:

db.ref("baskets").orderByChild("owner")
                 .equalTo(auth.currentUser.uid)
                 .on("value", cb)                 // Would succeed

However, queries that do not include the parameters in the rule would fail with a PermissionDenied error:

db.ref("baskets").on("value", cb)                 // Would fail with PermissionDenied

You can also use query-based rules to limit how much data a client downloads through read operations.

For example, the following rule limits read access to only the first 1000 results of a query, as ordered by priority:

messages: {
  ".read": "query.orderByKey &&
            query.limitToFirst <= 1000"
}

// Example queries:

db.ref("messages").on("value", cb)                // Would fail with PermissionDenied

db.ref("messages").limitToFirst(1000)
                  .on("value", cb)                // Would succeed (default order by key)

The following query. expressions are available in Realtime Database Security Rules .

Query-based rule expressions
بیان تایپ کنید توضیحات
query.orderByKey
query.orderByPriority
query.orderByValue
بولی True for queries ordered by key, priority, or value. False otherwise.
query.orderByChild رشته
تهی
Use a string to represent the relative path to a child node. For example, query.orderByChild === "address/zip" . If the query isn't ordered by a child node, this value is null.
query.startAt
query.endAt
query.equalTo
رشته
شماره
بولی
تهی
Retrieves the bounds of the executing query, or returns null if there is no bound set.
query.limitToFirst
query.limitToLast
شماره
تهی
Retrieves the limit on the executing query, or returns null if there is no limit set.

اپراتورها

Realtime Database Rules support a number of operators you can use to combine variables in the condition statement. See the full list of operators in the reference documentation .

Creating conditions

Your actual conditions will vary based on the access you want to grant. Rules intentionally offer an enormous degree of flexibility, so your app's rules can ultimately be as simple or as complex as you need them to be.

For some guidance creating simple, production-ready Rules , see Basic Security Rules .