เรียนรู้ไวยากรณ์หลักของภาษาของกฎการรักษาความปลอดภัยของ Firebase สำหรับ Cloud Storage

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

คู่มือนี้จะอธิบายไวยากรณ์และโครงสร้างพื้นฐานของ Cloud Storage Security Rules เพื่อ สร้างชุดกฎที่สมบูรณ์

การประกาศบริการและฐานข้อมูล

Firebase Security Rules สำหรับ Cloud Storage จะเริ่มต้นด้วยการประกาศต่อไปนี้เสมอ

service firebase.storage {
    // ...
}

การประกาศ service firebase.storage จะกำหนดขอบเขตของกฎเป็น Cloud Storage เพื่อป้องกันความขัดแย้งระหว่าง Cloud Storage Security Rules กับ กฎสำหรับผลิตภัณฑ์อื่นๆ เช่น Cloud Firestore

กฎการอ่าน/เขียนพื้นฐาน

กฎพื้นฐานประกอบด้วยคำสั่ง match ที่ระบุ Cloud Storage บัคเก็ต, คำสั่ง match ที่ระบุชื่อไฟล์ และนิพจน์ allow ที่ระบุรายละเอียดเมื่อได้รับอนุญาตให้อ่านข้อมูลที่ระบุ นิพจน์ allow จะระบุ วิธีการเข้าถึง (เช่น อ่าน เขียน) ที่เกี่ยวข้อง และ เงื่อนไข ที่จะอนุญาตหรือปฏิเสธการเข้าถึง

ในชุดกฎเริ่มต้น คำสั่ง match แรกจะใช้นิพจน์ไวลด์การ์ด {bucket} เพื่อระบุว่ากฎมีผลกับบัคเก็ตทั้งหมดในโปรเจ็กต์ เราจะพูดถึงแนวคิดเรื่องการจับคู่ไวลด์การ์ดเพิ่มเติมในส่วนถัดไป

service firebase.storage {
  // The {bucket} wildcard indicates we match files in all Cloud Storage buckets
  match /b/{bucket}/o {
    // Match filename
    match /filename {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

คำสั่ง match ทั้งหมดจะชี้ไปยังไฟล์ คำสั่ง match สามารถชี้ไปยังไฟล์ที่เฉพาะเจาะจงได้ เช่น match /images/profilePhoto.png

ไวลด์การ์ด match

นอกเหนือจากการชี้ไปยังไฟล์เดียวแล้ว Security Rules ยังสามารถใช้ ไวลด์การ์ด เพื่อชี้ไปยังไฟล์ใดก็ตามที่มีคำนำหน้าสตริงที่กำหนดในชื่อ ซึ่งรวมถึงเครื่องหมายทับ เช่น match /images/{imageId}

ในตัวอย่างด้านบน คำสั่ง match จะใช้ไวยากรณ์ไวลด์การ์ด {imageId} ซึ่งหมายความว่ากฎจะมีผลกับไฟล์ใดก็ตามที่มี /images/ อยู่ที่จุดเริ่มต้นของชื่อ เช่น /images/profilePhoto.png หรือ /images/croppedProfilePhoto.png เมื่อมีการประเมินนิพจน์ allow ในคำสั่ง match ตัวแปร imageId จะเปลี่ยนเป็นชื่อไฟล์รูปภาพ เช่น profilePhoto.png หรือ croppedProfilePhoto.png

ตัวแปรไวลด์การ์ดสามารถอ้างอิงได้จากภายใน match เพื่อให้สิทธิ์ชื่อไฟล์หรือเส้นทาง

// Another way to restrict the name of a file
match /images/{imageId} {
  allow read: if imageId == "profilePhoto.png";
}

ข้อมูลแบบลำดับชั้น

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

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

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      allow read, write: if <condition>;
    }

    // Explicitly define rules for the 'mp3s' pattern
    match /mp3s/{mp3Id} {
      allow read, write: if <condition>;
    }
  }
}

เมื่อซ้อนคำสั่ง match ระบบจะผนวกเส้นทางของคำสั่ง match ด้านในเข้ากับเส้นทางของคำสั่ง match ด้านนอกเสมอ ดังนั้นชุดกฎ 2 ชุดต่อไปนี้จึงมีความหมายเหมือนกัน

service firebase.storage {
  match /b/{bucket}/o {
    match /images {
      // Exact match for "images/profilePhoto.png"
      match /profilePhoto.png {
        allow write: if <condition>;
      }
    }
  }
}
service firebase.storage {
  match /b/{bucket}/o {
    // Exact match for "images/profilePhoto.png"
    match /images/profilePhoto.png {
      allow write: if <condition>;
      }
  }
}

ไวลด์การ์ด match แบบเรียกซ้ำ

นอกเหนือจากไวลด์การ์ดที่จับคู่และแสดงผลสตริงที่ส่วนท้ายของชื่อไฟล์แล้ว คุณยังประกาศไวลด์การ์ดหลายส่วน สำหรับการจับคู่ที่ซับซ้อนมากขึ้นได้โดย การเพิ่ม =** ลงในชื่อไวลด์การ์ด เช่น {path=**}

// Partial match for files that start with "images"
match /images {

  // Exact match for "images/**"
  // e.g. images/users/user:12345/profilePhoto.png is matched
  // images/profilePhoto.png is also matched!
  match /{allImages=**} {
    // This rule matches one or more path segments (**)
    // allImages is a path that contains all segments matched
    allow read: if <other_condition>;
  }
}

หากมีกฎหลายข้อที่ตรงกับไฟล์ ผลลัพธ์จะเป็น OR ของผลลัพธ์การประเมินกฎทั้งหมด กล่าวคือ หากกฎใดก็ตามที่ไฟล์ตรงกันประเมินเป็น true ผลลัพธ์จะเป็น true

ในกฎด้านบน ไฟล์ "images/profilePhoto.png" จะอ่านได้หาก condition หรือ other_condition ประเมินเป็นจริง ในขณะที่ไฟล์ "images/users/user:12345/profilePhoto.png" จะขึ้นอยู่กับผลลัพธ์ของ other_condition เท่านั้น

Cloud Storage Security Rules จะไม่เรียงซ้อน และระบบจะประเมินกฎก็ต่อเมื่อ เส้นทางคำขอตรงกับเส้นทางที่มีการระบุกฎไว้เท่านั้น

เวอร์ชัน 1

Firebase Security Rules จะใช้เวอร์ชัน 1 โดยค่าเริ่มต้น ในเวอร์ชัน 1 ไวลด์การ์ดแบบเรียกซ้ำจะจับคู่องค์ประกอบชื่อไฟล์อย่างน้อย 1 รายการ ไม่ใช่ 0 รายการขึ้นไป ดังนั้น match /images/{filenamePrefixWildcard}/{imageFilename=**} จะจับคู่ชื่อไฟล์ เช่น /images/profilePics/profile.png แต่ไม่ใช่ /images/badge.png ให้ใช้ /images/{imagePrefixorFilename=**} แทน

ไวลด์การ์ดแบบเรียกซ้ำต้องอยู่ที่ส่วนท้ายของคำสั่ง match

เราขอแนะนำให้คุณใช้เวอร์ชัน 2 เนื่องจากมีฟีเจอร์ที่มีประสิทธิภาพมากกว่า

เวอร์ชัน 2

ในเวอร์ชัน 2 ของ Firebase Security Rules ไวลด์การ์ดแบบเรียกซ้ำจะจับคู่รายการเส้นทาง 0 รายการขึ้นไป ดังนั้น /images/{filenamePrefixWildcard}/{imageFilename=**} จะจับคู่ชื่อไฟล์ /images/profilePics/profile.png และ /images/badge.png

คุณต้องเลือกใช้เวอร์ชัน 2 โดยเพิ่ม rules_version = '2'; ที่ด้านบนของ กฎความปลอดภัย

rules_version = '2';
service cloud.storage {
  match /b/{bucket}/o {
   ...
 }
}

คุณใช้ไวลด์การ์ดแบบเรียกซ้ำได้มากที่สุด 1 รายการต่อคำสั่ง match แต่ในเวอร์ชัน 2 คุณสามารถวางไวลด์การ์ดนี้ไว้ที่ใดก็ได้ในคำสั่ง match เช่น

rules_version = '2';
service firebase.storage {
 match /b/{bucket}/o {
   // Matches any file in a songs "subdirectory" under the
   // top level of your Cloud Storage bucket.
   match /{prefixSegment=**}/songs/{mp3filenames} {
     allow read, write: if <condition>;
   }
  }
}

การดำเนินการแบบละเอียด

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

การดำเนินการ read สามารถแบ่งออกเป็น get และ list

กฎ write สามารถแบ่งออกเป็น create, update และ delete

service firebase.storage {
  match /b/{bucket}/o {
    // A read rule can be divided into read and list rules
    match /images/{imageId} {
      // Applies to single file read requests
      allow get: if <condition>;
      // Applies to list and listAll requests (Security Rules Version 2)
      allow list: if <condition>;

    // A write rule can be divided into create, update, and delete rules
    match /images/{imageId} {
      // Applies to writes to file contents
      allow create: if <condition>;

      // Applies to updates to (pre-existing) file metadata
      allow update: if <condition>;

      // Applies to delete operations
      allow delete: if <condition>;
    }
  }
 }
}

คำสั่ง match ที่ทับซ้อนกัน

ชื่อไฟล์อาจตรงกับคำสั่ง match มากกว่า 1 รายการ ในกรณีที่นิพจน์ allow หลายรายการตรงกับคำขอ ระบบจะอนุญาตการเข้าถึงหากเงื่อนไขใดก็ตาม เป็น true

service firebase.storage {
  match b/{bucket}/o {
    // Matches file names directly inside of '/images/'.
    match /images/{imageId} {
      allow read, write: if false;
    }

    // Matches file names anywhere under `/images/`
    match /images/{imageId=**} {
      allow read, write: if true;
    }
  }
}

ในตัวอย่างด้านบน ระบบจะอนุญาตการอ่านและการเขียนทั้งหมดลงในไฟล์ที่มีชื่อขึ้นต้นด้วย /images/ เนื่องจากกฎข้อที่ 2 เป็น true เสมอ แม้ว่ากฎข้อแรกจะเป็น false

กฎไม่ใช่ตัวกรอง

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

ตัวอย่างเช่น กฎความปลอดภัยต่อไปนี้

service firebase.storage {
  match /b/{bucket}/o {
    // Allow the client to read files with contentType 'image/png'
    match /aFileNamePrefix/{aFileName} {
      allow read: if resource.contentType == 'image/png';
    }
  }
}

ปฏิเสธ: กฎนี้ปฏิเสธ คำขอต่อไปนี้เนื่องจากชุดผลลัพธ์อาจมีไฟล์ที่ contentType ไม่ใช่ image/png

เว็บ
filesRef = storage.ref().child("aFilenamePrefix");

filesRef.listAll()
    .then(function(result) {
      console.log("Success: ", result.items);
    })
});

กฎใน Cloud Storage Security Rules จะประเมินการค้นหาแต่ละรายการเทียบกับผลลัพธ์ที่เป็นไปได้ และจะทำให้คำขอไม่สำเร็จหากการค้นหาอาจแสดงไฟล์ที่ไคลเอ็นต์ไม่มีสิทธิ์ อ่าน คำขอเข้าถึงต้องเป็นไปตามข้อจำกัดที่กฎกำหนด

ขั้นตอนถัดไป

คุณสามารถทำความเข้าใจ Firebase Security Rules สำหรับ Cloud Storage ให้ลึกซึ้งยิ่งขึ้นได้ดังนี้

  • เรียนรู้แนวคิดหลักถัดไปของภาษา Rules ซึ่งก็คือเงื่อนไขแบบไดนามิก ที่ช่วยให้กฎตรวจสอบการให้สิทธิ์ผู้ใช้ เปรียบเทียบข้อมูลที่มีอยู่กับข้อมูลที่เข้ามา ตรวจสอบข้อมูลที่เข้ามา และอื่นๆ

  • ตรวจสอบกรณีการใช้งานด้านความปลอดภัยทั่วไปและ Firebase Security Rules คำจำกัดความที่ใช้ในกรณีดังกล่าว

คุณสามารถสำรวจกรณีการใช้งาน Firebase Security Rules ที่เฉพาะเจาะจงกับ Cloud Storage ได้ดังนี้