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

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

คำแนะนำนี้อธิบาย Use Case พื้นฐานบางอย่างที่คุณอาจต้องการ นำไปใช้เมื่อตั้งค่าแอปและปกป้องข้อมูล อย่างไรก็ตาม ก่อนที่จะเริ่มเขียนกฎ คุณอาจต้องดูข้อมูลเพิ่มเติมเกี่ยวกับภาษาที่ใช้เขียนกฎและลักษณะการทำงานของกฎ

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