قوانین اساسی امنیت

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

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

برای دسترسی و به‌روزرسانی قوانین خود، مراحل ذکر شده در مدیریت و استقرار Firebase Security Rules دنبال کنید.

قوانین پیش‌فرض: حالت قفل‌شده

وقتی در کنسول Firebase یک پایگاه داده یا نمونه ذخیره‌سازی ایجاد می‌کنید، می‌توانید انتخاب کنید که آیا Firebase Security Rules شما دسترسی به داده‌هایتان را محدود کند ( حالت قفل‌شده ) یا به هر کسی اجازه دسترسی بدهد ( حالت آزمایشی ). در Cloud Firestore و Realtime Database ، قوانین پیش‌فرض برای حالت قفل‌شده، دسترسی همه کاربران را سلب می‌کند. در Cloud Storage ، فقط کاربران احراز هویت‌شده می‌توانند به سطل‌های ذخیره‌سازی دسترسی داشته باشند.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Realtime Database

{
  "rules": {
    ".read": false,
    ".write": false
  }
}

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if false;
    }
  }
}

قوانین توسعه-محیط زیست

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

به یاد داشته باشید که فایربیس به کلاینت‌ها اجازه دسترسی مستقیم به داده‌های شما را می‌دهد و Firebase Security Rules تنها محافظی هستند که دسترسی کاربران مخرب را مسدود می‌کنند. تعریف قوانین جدا از منطق محصول مزایای متعددی دارد: کلاینت‌ها مسئول اجرای امنیت نیستند، پیاده‌سازی‌های دارای باگ، داده‌های شما را به خطر نمی‌اندازند و از همه مهمتر، شما برای محافظت از داده‌ها در برابر جهان به یک سرور واسطه متکی نیستید.

همه کاربران احراز هویت شده

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

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    match /some_collection/{document} {
      allow read, write: if request.auth != null;
    }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      ".read": "auth.uid !== null",
      ".write": "auth.uid !== null"
    }
  }
}

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    match /some_folder/{fileName} {
      allow read, write: if request.auth != null;
    }
  }
}

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

همانطور که برای استقرار برنامه خود آماده می‌شوید، مطمئن شوید که داده‌های شما محافظت می‌شوند و دسترسی به درستی به کاربران شما اعطا می‌شود. از Authentication برای تنظیم دسترسی مبتنی بر کاربر استفاده کنید و مستقیماً از پایگاه داده خود بخوانید تا دسترسی مبتنی بر داده را تنظیم کنید.

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

دسترسی فقط برای مالک محتوا

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

چه زمانی این قانون کار می‌کند: این قانون در صورتی خوب کار می‌کند که داده‌ها توسط کاربر دسته‌بندی شده باشند - اگر تنها کاربری که نیاز به دسترسی به داده‌ها دارد، همان کاربری باشد که داده‌ها را ایجاد کرده است.

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

برای تنظیم این قانون: قانونی ایجاد کنید که تأیید کند کاربری که درخواست دسترسی برای خواندن یا نوشتن داده‌ها را دارد، مالک آن داده‌ها است.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow only authenticated content owners access
    match /some_collection/{userId}/{document} {
      allow read, write: if request.auth != null && request.auth.uid == userId
    }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "$uid": {
        // Allow only authenticated content owners access to their data
        ".read": "auth !== null && auth.uid === $uid",
        ".write": "auth !== null && auth.uid === $uid"
      }
    }
  }
}

Cloud Storage

// Grants a user access to a node matching their user ID
service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/file.txt"
    match /user/{userId}/{fileName} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

دسترسی مختلط عمومی و خصوصی

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

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

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

برای تنظیم این قانون: قانونی ایجاد کنید که دسترسی خواندن را برای همه کاربران (یا همه کاربران احراز هویت شده) فعال کند و تأیید کند که کاربرِ در حال نوشتن داده‌ها، مالک آنهاست.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow public read access, but only content owners can write
    match /some_collection/{document} {
      // Allow public reads
      allow read: if true
      // Allow creation if the current user owns the new document
      allow create: if request.auth.uid == request.resource.data.author_uid;
      // Allow updates by the owner, and prevent change of ownership
      allow update: if request.auth.uid == request.resource.data.author_uid
                    && request.auth.uid == resource.data.author_uid;
      // Allow deletion if the current user owns the existing document
      allow delete: if request.auth.uid == resource.data.author_uid;
    }
  }
}

Realtime Database

{
// Allow anyone to read data, but only authenticated content owners can
// make changes to their data

  "rules": {
    "some_path": {
      "$uid": {
        ".read": true,
        // or ".read": "auth.uid !== null" for only authenticated users
        ".write": "auth.uid === $uid"
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/file.txt"
    match /user/{userId}/{fileName} {
      allow read;
      allow write: if request.auth.uid == userId;
    }
  }
}

دسترسی مبتنی بر ویژگی و مبتنی بر نقش

برای اینکه این قوانین کار کنند، باید در داده‌های خود، ویژگی‌هایی را به کاربران تعریف و اختصاص دهید. Firebase Security Rules درخواست را با داده‌های موجود در پایگاه داده یا فراداده فایل شما بررسی می‌کنند تا دسترسی را تأیید یا رد کنند.

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

وقتی این قانون کار نمی‌کند: در Realtime Database و Cloud Storage ، قوانین شما نمی‌توانند از متد get() که قوانین Cloud Firestore می‌توانند در آن بگنجانند، استفاده کنند. در نتیجه، شما باید پایگاه داده یا فراداده‌ی فایل خود را طوری ساختار دهید که ویژگی‌هایی را که در قوانین خود استفاده می‌کنید، منعکس کند.

برای تنظیم این قانون: در Cloud Firestore ، فیلدی را در اسناد کاربران خود قرار دهید که بتوانید آن را بخوانید، سپس قانون خود را طوری ساختار دهید که آن فیلد را بخواند و به طور مشروط به آن دسترسی بدهد. در Realtime Database ، یک مسیر داده ایجاد کنید که کاربران برنامه شما را تعریف کند و به آنها نقشی در یک گره فرزند اعطا کند.

همچنین می‌توانید ادعاهای سفارشی را در Authentication تنظیم کنید و سپس آن اطلاعات را از متغیر auth.token در هر یک از Firebase Security Rules بازیابی کنید.

ویژگی‌ها و نقش‌های تعریف‌شده توسط داده

این قوانین فقط در Cloud Firestore و Realtime Database کار می‌کنند.

Cloud Firestore

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

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, Check a boolean `admin` attribute
    allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
    allow read: true;

    // Alterntatively, for role-based access, assign specific roles to users
    match /some_collection/{document} {
     allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Reader"
     allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Writer"
   }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "${subpath}": {
        //
        ".write": "root.child('users').child(auth.uid).child('role').val() === 'admin'",
        ".read": true
      }
    }
  }
}

ویژگی‌ها و نقش‌های ادعای سفارشی

برای پیاده‌سازی این قوانین، ادعاهای سفارشی را در Firebase Authentication تنظیم کنید و سپس از ادعاها در قوانین خود استفاده کنید.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, check for an administrator claim
    allow write: if request.auth.token.admin == true;
    allow read: true;

    // Alterntatively, for role-based access, assign specific roles to users
    match /some_collection/{document} {
     allow read: if request.auth.token.reader == "true";
     allow write: if request.auth.token.writer == "true";
   }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "$uid": {
        // Create a custom claim for each role or group
        // you want to use
        ".write": "auth.uid !== null && auth.token.writer === true",
        ".read": "auth.uid !== null && auth.token.reader === true"
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  // 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;
  }
}

ویژگی‌های اجاره

برای پیاده‌سازی این قوانین، قابلیت چند مستاجری (multitenancy) را در پلتفرم هویت ابری گوگل (GCIP) تنظیم کنید و سپس از مستاجر در قوانین خود استفاده کنید. مثال‌های زیر اجازه نوشتن از یک کاربر در یک مستاجر خاص، به عنوان مثال، tenant2-m6tyz را می‌دهند.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // For tenant-based access control, check for a tenantID
    allow write: if request.auth.token.firebase.tenant == 'tenant2-m6tyz';
    allow read: true;
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "$uid": {
        // Only allow reads and writes if user belongs to a specific tenant
        ".write": "auth.uid !== null && auth.token.firebase.tenant === 'tenant2-m6tyz'",
        ".read": "auth.uid !== null
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  // Only allow reads and writes if user belongs to a specific tenant
  match /files/{tenantId}/{fileName} {
    allow read: if request.auth != null;
    allow write: if request.auth.token.firebase.tenant == tenantId;
  }
}