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

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

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

หากต้องการใช้กฎเหล่านี้ ให้ตั้งค่า การเช่าหลายรายการใน 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;
  }
}