Catch up on highlights from Firebase at Google I/O 2023. Learn more

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

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

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

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

กฎความปลอดภัยของ Firebase สำหรับ Cloud Storage จะเริ่มต้นด้วยการประกาศต่อไปนี้เสมอ:

service firebase.storage {
    // ...
}

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

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

กฎพื้นฐานประกอบด้วยคำสั่งจับ match ที่ระบุที่เก็บข้อมูล Cloud Storage คำสั่งจับคู่ที่ระบุชื่อไฟล์ และ 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 /images/profilePhoto.png

จับคู่สัญลักษณ์ตัวแทน

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

ในตัวอย่างข้างต้น คำสั่งการจับคู่ใช้รูปแบบไวด์การ์ด {imageId} ซึ่งหมายความว่ากฎนี้ใช้กับไฟล์ใดๆ ที่มี /images/ ที่จุดเริ่มต้นของชื่อ เช่น /images/profilePhoto.png หรือ /images/croppedProfilePhoto.png เมื่อนิพจน์ allow ในคำสั่งการจับคู่ได้รับการประเมิน ตัวแปร 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 โต้ตอบกับชื่อไฟล์เหล่านี้อย่างไร

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

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 ภายนอกเสมอ ชุดกฎสองชุดต่อไปนี้จึงเทียบเท่ากัน:

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

สัญลักษณ์ตัวแทนการแข่งขันแบบเรียกซ้ำ

นอกจากไวด์การ์ดที่จับคู่และส่งคืนสตริงที่ส่วนท้ายของชื่อไฟล์แล้ว ไวลด์การ์ดหลายเซ็กเมนต์ สามารถประกาศสำหรับการจับคู่ที่ซับซ้อนยิ่งขึ้นโดยเพิ่ม =** ต่อชื่อไวด์การ์ด เช่น {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 ไม่เรียงซ้อน และกฎจะได้รับการประเมินเมื่อเส้นทางคำขอตรงกับเส้นทางที่มีกฎระบุไว้เท่านั้น

รุ่น 1

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

สัญลักษณ์ตัวแทนแบบเรียกซ้ำต้องมาที่ส่วนท้ายของคำสั่งการแข่งขัน

เราขอแนะนำให้คุณใช้เวอร์ชัน 2 สำหรับคุณสมบัติที่มีประสิทธิภาพยิ่งขึ้น

เวอร์ชัน 2

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

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

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

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

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 (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 มากกว่าหนึ่งคำสั่ง ในกรณีที่ 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/ เนื่องจากกฎข้อที่สองเป็น 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);
    })
});

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

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

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

คุณสามารถสำรวจกรณีการใช้กฎความปลอดภัยของ Firebase เฉพาะสำหรับ Cloud Storage: