กฎความปลอดภัยพื้นฐาน

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;
    }
  }
}

กฎสภาพแวดล้อมการพัฒนา

ขณะที่คุณกำลังทำงานกับแอป คุณอาจต้องการสิทธิ์เข้าถึงข้อมูลที่ค่อนข้างเปิดกว้างหรือไม่มีข้อจำกัด โปรดอย่าลืมอัปเดตSecurity Rules ก่อน ที่จะติดตั้งใช้งานแอปในเวอร์ชันที่ใช้งานจริง และโปรดทราบว่าหากคุณติดตั้งใช้งานแอป แอปจะเข้าถึงได้แบบสาธารณะ แม้ว่าคุณจะยังไม่ได้ เปิดตัวแอปก็ตาม

โปรดทราบว่า Firebase อนุญาตให้ไคลเอ็นต์เข้าถึงข้อมูลของคุณได้โดยตรง และ 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;
  }
}

แอตทริบิวต์การเช่า

หากต้องการใช้กฎเหล่านี้ ให้ตั้งค่า การแบ่งการใช้ทรัพยากรให้ผู้ใช้จำนวนมาก (Multi-Tenancy)ใน Google Cloud Identity Platform (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;
  }
}