از شرایط در قوانین امنیتی Firebase Cloud Storage استفاده کنید

این راهنما مبتنی بر یادگیری نحو اصلی راهنمای زبان Firebase Security Rules است تا نحوه افزودن شرایط به قوانین امنیتی Firebase برای فضای ذخیره‌سازی ابری را نشان دهد.

بلوک اصلی ساختمان قوانین امنیتی Cloud Storage شرط است. شرط یک عبارت بولی است که تعیین می کند آیا یک عملیات خاص باید مجاز یا رد شود. برای قوانین اساسی، استفاده از لفظ های true و false به عنوان شرایط کاملاً خوب عمل می کند. اما قوانین امنیتی Firebase برای زبان Cloud Storage راه هایی را برای نوشتن شرایط پیچیده تری به شما ارائه می دهد که می تواند:

  • احراز هویت کاربر را بررسی کنید
  • اعتبار سنجی داده های دریافتی

احراز هویت

قوانین امنیتی Firebase برای Cloud Storage با Firebase Authentication ادغام می شود تا احراز هویت قدرتمند مبتنی بر کاربر را برای Cloud Storage فراهم کند. این امکان کنترل دسترسی گرانول را بر اساس ادعاهای یک نشانه Firebase Authentication فراهم می کند.

هنگامی که یک کاربر احراز هویت درخواستی را علیه فضای ذخیره سازی ابری انجام می دهد، متغیر request.auth با uid کاربر ( request.auth.uid ) و همچنین ادعاهای Firebase Authentication JWT ( request.auth.token ) پر می شود.

علاوه بر این، هنگام استفاده از احراز هویت سفارشی، ادعاهای اضافی در قسمت request.auth.token ظاهر می شود.

هنگامی که یک کاربر احراز هویت نشده درخواستی را انجام می دهد، متغیر request.auth null است.

با استفاده از این داده ها، چندین روش رایج برای استفاده از احراز هویت برای ایمن سازی فایل ها وجود دارد:

  • عمومی: نادیده گرفتن request.auth
  • خصوصی تأیید شده: بررسی کنید که request.auth null نیست
  • کاربر خصوصی: بررسی کنید که request.auth.uid برابر با uid مسیر باشد
  • گروه خصوصی: ادعاهای نشانه سفارشی را بررسی کنید تا با ادعای انتخابی مطابقت داشته باشد، یا فراداده فایل را بخوانید تا ببینید آیا یک قسمت فراداده وجود دارد یا خیر.

عمومی

هر قانونی که زمینه request.auth در نظر نگیرد، می‌تواند یک قانون public در نظر گرفته شود، زیرا زمینه احراز هویت کاربر را در نظر نمی‌گیرد. این قوانین می‌تواند برای نمایش داده‌های عمومی مانند دارایی‌های بازی، فایل‌های صوتی یا سایر محتوای ثابت مفید باشد.

// Anyone to read a public image if the file is less than 100kB
// Anyone can upload a public file ending in '.txt'
match /public/{imageId} {
  allow read: if resource.size < 100 * 1024;
  allow write: if imageId.matches(".*\\.txt");
}

خصوصی تایید شده

در موارد خاص، ممکن است بخواهید داده ها توسط همه کاربران احراز هویت شده برنامه شما قابل مشاهده باشد، اما توسط کاربران احراز هویت نشده قابل مشاهده نباشد. از آنجایی که متغیر request.auth برای همه کاربران احراز هویت نشده null است، تنها کاری که باید انجام دهید این است که وجود متغیر request.auth را بررسی کنید تا به احراز هویت نیاز داشته باشید:

// Require authentication on all internal image reads
match /internal/{imageId} {
  allow read: if request.auth != null;
}

کاربر خصوصی

تا حد زیادی رایج ترین مورد استفاده برای request.auth ارائه مجوزهای جزئی به کاربران در فایل هایشان است: از آپلود تصاویر نمایه تا خواندن اسناد خصوصی.

از آنجایی که فایل‌های موجود در فضای ذخیره‌سازی ابری دارای یک «مسیر» کامل به فایل هستند، تنها چیزی که لازم است برای ایجاد فایلی که توسط کاربر کنترل می‌شود، تکه‌ای از اطلاعات شناسایی منحصربه‌فرد کاربر در پیشوند نام فایل (مانند uid کاربر) است که می‌توان آن را بررسی کرد. هنگامی که قانون ارزیابی می شود:

// Only a user can upload their profile picture, but anyone can view it
match /users/{userId}/profilePicture.png {
  allow read;
  allow write: if request.auth.uid == userId;
}

گروه خصوصی

یکی دیگر از موارد استفاده به همان اندازه رایج، اجازه دادن مجوزهای گروه بر روی یک شی است، مانند اجازه دادن به چندین عضو تیم برای همکاری در یک سند مشترک. چندین روش برای انجام این کار وجود دارد:

  • یک توکن سفارشی احراز هویت Firebase که حاوی اطلاعات اضافی در مورد یکی از اعضای گروه (مانند شناسه گروه) است، ایجاد کنید.
  • شامل اطلاعات گروه (مانند شناسه گروه یا لیستی از uid های مجاز) در فراداده فایل

هنگامی که این داده ها در فراداده توکن یا فایل ذخیره می شوند، می توان از داخل یک قانون به آن ارجاع داد:

// Allow reads if the group ID in your token matches the file metadata's `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
  allow read: if resource.metadata.owner == request.auth.token.groupId;
  allow write: if request.auth.token.groupId == groupId;
}

درخواست ارزیابی

آپلودها، بارگیری‌ها، تغییرات فراداده و حذف‌ها با استفاده از request ارسال شده به فضای ذخیره‌سازی ابری ارزیابی می‌شوند. علاوه بر شناسه منحصر به فرد کاربر و بارگذاری Firebase Authentication در شی request.auth همانطور که در بالا توضیح داده شد، متغیر request شامل مسیر فایلی است که درخواست در آن انجام می شود، زمان دریافت درخواست و مقدار resource جدید در صورتی که درخواست نوشتن است

شی request همچنین شامل شناسه منحصر به فرد کاربر و بارگذاری Firebase Authentication در شی request.auth است که در بخش امنیت مبتنی بر کاربر اسناد بیشتر توضیح داده خواهد شد.

لیست کاملی از خواص در شی request در زیر موجود است:

ویژگی تایپ کنید شرح
auth نقشه<رشته، رشته> زمانی که کاربر وارد سیستم می‌شود، uid ، شناسه منحصربه‌فرد کاربر، و token ، نقشه‌ای از Firebase Authentication JWT را ارائه می‌کند. در غیر این صورت null خواهد شد.
params نقشه<رشته، رشته> نقشه حاوی پارامترهای پرس و جو درخواست.
path مسیر path که نشان دهنده مسیری است که درخواست در آن انجام می شود.
resource نقشه<رشته، رشته> مقدار منبع جدید، فقط در درخواست‌های write وجود دارد.
time مهر زمانی یک مهر زمانی که نشان دهنده زمان ارزیابی درخواست سرور است.

ارزیابی منابع

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

قوانین امنیتی Firebase برای ذخیره‌سازی ابری، ابرداده‌های فایل را در شی resource ارائه می‌کند، که شامل جفت‌های کلید/مقدار از ابرداده‌های ظاهر شده در یک شی Cloud Storage است. این ویژگی ها را می توان در درخواست های read یا write برای اطمینان از یکپارچگی داده ها بررسی کرد.

در درخواست‌های write (مانند آپلود، به‌روزرسانی فراداده و حذف)، علاوه بر شی resource ، که حاوی فراداده فایل برای فایلی است که در حال حاضر در مسیر درخواست وجود دارد، شما همچنین می‌توانید از شی request.resource استفاده کنید. که حاوی زیرمجموعه ای از فراداده فایل است که در صورت مجاز بودن نوشتن نوشته می شود. می توانید از این دو مقدار برای اطمینان از یکپارچگی داده ها یا اعمال محدودیت های برنامه مانند نوع یا اندازه فایل استفاده کنید.

لیست کاملی از خواص در شی resource در زیر موجود است:

ویژگی تایپ کنید شرح
name رشته نام کامل شی
bucket رشته نام سطلی که این شی در آن قرار دارد.
generation بین المللی تولید شیء Google Cloud Storage از این شی.
metageneration بین المللی فراتولید شی Google Cloud Storage این شی.
size بین المللی اندازه شی در بایت.
timeCreated مهر زمانی مهر زمانی که نشان دهنده زمان ایجاد یک شی است.
updated مهر زمانی مهر زمانی که نشان‌دهنده زمان آخرین به‌روزرسانی یک شی است.
md5Hash رشته هش MD5 از شی.
crc32c رشته یک هش crc32c از شی.
etag رشته تگ مرتبط با این شی.
contentDisposition رشته محتوای محتوای مرتبط با این شی.
contentEncoding رشته رمزگذاری محتوای مرتبط با این شی.
contentLanguage رشته زبان محتوای مرتبط با این شی.
contentType رشته نوع محتوای مرتبط با این شی.
metadata نقشه<رشته، رشته> جفت کلید/مقدار متادیتای سفارشی اضافی و مشخص شده توسط توسعه دهنده.

request.resource شامل همه اینها به استثنای generation , metageneration , etag , timeCreated و updated .

با Cloud Firestore تقویت کنید

برای ارزیابی سایر معیارهای مجوز می توانید به اسناد موجود در Cloud Firestore دسترسی داشته باشید.

با استفاده از توابع firestore.get() و firestore.exists() ، قوانین امنیتی شما می توانند درخواست های دریافتی را در برابر اسناد موجود در Cloud Firestore ارزیابی کنند. توابع firestore.get() و firestore.exists() هر دو انتظار مسیرهای سند کاملاً مشخص را دارند. هنگام استفاده از متغیرها برای ساخت مسیرهایی برای firestore.get() و firestore.exists() ، باید به طور صریح از متغیرها با استفاده از دستور $(variable) فرار کنید.

در مثال زیر، قانونی را مشاهده می‌کنیم که دسترسی خواندن به فایل‌ها را برای کاربرانی که عضو باشگاه‌های خاصی هستند، محدود می‌کند.

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{club}/files/{fileId} {
      allow read: if club in
        firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships
    }
  }
}
در مثال بعدی، فقط دوستان کاربر می توانند عکس های آنها را ببینند.
service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/photos/{fileId} {
      allow read: if
        firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id))
    }
  }
}

پس از ایجاد و ذخیره اولین قوانین امنیتی Cloud Storage خود که از این توابع Cloud Firestore استفاده می‌کنند، در کنسول Firebase یا Firebase CLI از شما خواسته می‌شود تا مجوزهای اتصال دو محصول را فعال کنید.

همانطور که در Manage and Deploy Security Rules Firebase توضیح داده شده است، می‌توانید این ویژگی را با حذف یک نقش IAM غیرفعال کنید.

اعتبارسنجی داده ها

قوانین امنیتی Firebase برای ذخیره‌سازی ابری همچنین می‌تواند برای اعتبارسنجی داده‌ها، از جمله اعتبارسنجی نام فایل و مسیر و همچنین ویژگی‌های فراداده فایل مانند contentType و size استفاده شود.

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      // Only allow uploads of any image file that's less than 5MB
      allow write: if request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }
  }
}

توابع سفارشی

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

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

یک تابع با کلمه کلیدی function تعریف می شود و صفر یا بیشتر آرگومان می گیرد. برای مثال، ممکن است بخواهید دو نوع شرط استفاده شده در مثال های بالا را در یک تابع واحد ترکیب کنید:

service firebase.storage {
  match /b/{bucket}/o {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }
    match /images/{imageId} {
      allow read, write: if signedInOrPublic();
    }
    match /mp3s/{mp3Ids} {
      allow read: if signedInOrPublic();
    }
  }
}

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

مراحل بعدی

پس از این بحث در مورد شرایط، شما درک پیچیده تری از قوانین دارید و آماده هستید:

نحوه رسیدگی به موارد استفاده اصلی را بیاموزید و گردش کار برای توسعه، آزمایش و استقرار قوانین را بیاموزید: