คู่มือนี้สร้างขึ้นจาก การเรียนรู้ไวยากรณ์หลักของคู่มือภาษากฎความปลอดภัยของ Firebase เพื่อแสดงวิธีเพิ่มเงื่อนไขให้กับกฎความปลอดภัย Firebase สำหรับ Cloud Storage
โครงสร้างหลักของกฎความปลอดภัยของ Cloud Storage คือ เงื่อนไข เงื่อนไขคือนิพจน์บูลีนที่กำหนดว่าควรอนุญาตหรือปฏิเสธการดำเนินการเฉพาะ สำหรับกฎพื้นฐาน การใช้ตัวอักษร true
และ false
ตามเงื่อนไขจะทำงานได้ดีอย่างสมบูรณ์ แต่กฎความปลอดภัยของ Firebase สำหรับภาษา Cloud Storage ช่วยให้คุณเขียนเงื่อนไขที่ซับซ้อนมากขึ้นได้ ซึ่งจะทำให้:
- ตรวจสอบการรับรองความถูกต้องของผู้ใช้
- ตรวจสอบข้อมูลขาเข้า
การรับรองความถูกต้อง
กฎความปลอดภัยของ Firebase สำหรับที่เก็บข้อมูลบนคลาวด์ผสานรวมกับการตรวจสอบสิทธิ์ของ Firebase เพื่อให้การรับรองความถูกต้องตามผู้ใช้ที่มีประสิทธิภาพไปยังที่เก็บข้อมูลบนคลาวด์ สิ่งนี้ทำให้สามารถควบคุมการเข้าถึงแบบละเอียดตามการอ้างสิทธิ์ของโทเค็นการตรวจสอบสิทธิ์ Firebase
เมื่อผู้ใช้ที่ผ่านการรับรองความถูกต้องดำเนินการร้องขอกับ Cloud Storage ตัวแปร request.auth
จะถูกเติมด้วย uid
ของผู้ใช้ ( request.auth.uid
) รวมทั้งการอ้างสิทธิ์ของ Firebase Authentication JWT ( request.auth.token
)
นอกจากนี้ เมื่อใช้การรับรองความถูกต้องแบบกำหนดเอง การอ้างสิทธิ์เพิ่มเติมจะแสดงในช่อง request.auth.token
เมื่อผู้ใช้ที่ไม่ผ่านการรับรองความถูกต้องทำการร้องขอ ตัวแปร request.auth
จะเป็น null
การใช้ข้อมูลนี้ มีวิธีทั่วไปหลายวิธีในการใช้การรับรองความถูกต้องเพื่อรักษาความปลอดภัยไฟล์:
- สาธารณะ: ละเว้น
request.auth
- รับรองความถูกต้องส่วนตัว: ตรวจสอบว่า
request.auth
ไม่เป็นnull
- ผู้ใช้ส่วนตัว: ตรวจสอบว่า
request.auth.uid
เท่ากับพาธuid
- จัดกลุ่มส่วนตัว: ตรวจสอบการอ้างสิทธิ์ของโทเค็นที่กำหนดเองเพื่อให้ตรงกับการอ้างสิทธิ์ที่เลือก หรืออ่านข้อมูลเมตาของไฟล์เพื่อดูว่ามีฟิลด์ข้อมูลเมตาอยู่หรือไม่
สาธารณะ
กฎใดๆ ที่ไม่พิจารณาบริบทของ request.auth
สามารถถือเป็นกฎ public
ได้ เนื่องจากไม่พิจารณาบริบทการรับรองความถูกต้องของผู้ใช้ กฎเหล่านี้มีประโยชน์สำหรับการแสดงข้อมูลสาธารณะ เช่น เนื้อหาของเกม ไฟล์เสียง หรือเนื้อหาคงที่อื่นๆ
// Anyone to read a public image if the file is less than 100kB // Anyone can upload a public file ending in '.txt' match /public/{imageId} { allow read: if resource.size < 100 * 1024; allow write: if imageId.matches(".*\\.txt"); }
ส่วนตัวรับรองความถูกต้อง
ในบางกรณี คุณอาจต้องการให้ผู้ใช้ที่ผ่านการรับรองความถูกต้องทั้งหมดของแอปพลิเคชันของคุณดูข้อมูลได้ แต่ไม่ใช่โดยผู้ใช้ที่ไม่ได้ตรวจสอบสิทธิ์ เนื่องจากตัวแปร request.auth
เป็นค่า null
สำหรับผู้ใช้ที่ไม่ได้รับการตรวจสอบสิทธิ์ทั้งหมด สิ่งที่คุณต้องทำคือตรวจ request.auth
ว่ามีตัวแปร
// Require authentication on all internal image reads match /internal/{imageId} { allow read: if request.auth != null; }
ผู้ใช้ส่วนตัว
กรณีการใช้งานที่พบบ่อยที่สุดสำหรับ request.auth
คือการให้สิทธิ์แบบละเอียดแก่ผู้ใช้แต่ละรายในไฟล์ของตน ตั้งแต่การอัปโหลดรูปโปรไฟล์ไปจนถึงการอ่านเอกสารส่วนตัว
เนื่องจากไฟล์ใน Cloud Storage มี "พาธ" แบบเต็มไปยังไฟล์ สิ่งที่ต้องทำทั้งหมดเพื่อสร้างไฟล์ที่ควบคุมโดยผู้ใช้คือชิ้นส่วนที่ไม่ซ้ำใคร ข้อมูลระบุผู้ใช้ในคำนำหน้าชื่อไฟล์ (เช่น uid
ของผู้ใช้) ที่ตรวจสอบได้ เมื่อกฎได้รับการประเมิน:
// Only a user can upload their profile picture, but anyone can view it match /users/{userId}/profilePicture.png { allow read; allow write: if request.auth.uid == userId; }
กลุ่มส่วนตัว
กรณีการใช้งานทั่วไปอีกกรณีหนึ่งคือการอนุญาตสิทธิ์แบบกลุ่มบนวัตถุ เช่น การอนุญาตให้สมาชิกในทีมหลายคนทำงานร่วมกันบนเอกสารที่แชร์ มีหลายวิธีในการทำเช่นนี้:
- สร้าง โทเค็นการรับรองความถูกต้อง ของ Firebase ที่มีข้อมูลเพิ่มเติมเกี่ยวกับสมาชิกกลุ่ม (เช่น รหัสกลุ่ม)
- รวมข้อมูลกลุ่ม (เช่น ID กลุ่มหรือรายการ
uid
ที่ได้รับอนุญาต) ใน ข้อมูลเมตาของไฟล์
เมื่อข้อมูลนี้ถูกจัดเก็บไว้ในโทเค็นหรือข้อมูลเมตาของไฟล์ จะสามารถอ้างอิงได้จากภายในกฎ:
// 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; }
ขอการประเมิน
การอัปโหลด ดาวน์โหลด การเปลี่ยนแปลงข้อมูลเมตา และการลบจะได้รับการประเมินโดยใช้ request
ที่ส่งไปยัง Cloud Storage นอกจาก ID เฉพาะของผู้ใช้และเพย์โหลดการตรวจสอบความถูกต้องของ Firebase ในออบเจกต์ request.auth
ตามที่อธิบายไว้ด้านบนแล้ว ตัวแปร request
ยังมีเส้นทางไฟล์ที่ดำเนินการตามคำขอ เวลาที่ได้รับคำขอ และค่า resource
ใหม่หาก คำขอเป็นการเขียน
วัตถุ request
ยังมี ID เฉพาะของผู้ใช้และเพย์โหลดการตรวจสอบความถูกต้องของ Firebase ในวัตถุ request.auth
ซึ่งจะอธิบายเพิ่มเติมในส่วน การรักษาความปลอดภัยตามผู้ใช้ ของเอกสาร
รายการคุณสมบัติทั้งหมดในออบเจกต์ request
มีอยู่ด้านล่าง:
คุณสมบัติ | พิมพ์ | คำอธิบาย |
---|---|---|
auth | แผนที่<string, string> | เมื่อผู้ใช้เข้าสู่ระบบ ให้ระบุ uid ID เฉพาะของผู้ใช้ และ token แผนที่ของการอ้างสิทธิ์ Firebase Authentication JWT มิฉะนั้นจะเป็น null |
params | แผนที่<string, string> | แผนที่ที่มีพารามิเตอร์การค้นหาของคำขอ |
path | เส้นทาง | path ที่แสดงเส้นทางที่คำขอกำลังดำเนินการอยู่ |
resource | แผนที่<string, string> | ค่าทรัพยากรใหม่ แสดงเฉพาะในคำขอ write |
time | การประทับเวลา | การประทับเวลาที่แสดงถึงเวลาของเซิร์ฟเวอร์ที่คำขอได้รับการประเมิน |
การประเมินทรัพยากร
เมื่อประเมินกฎ คุณอาจต้องการประเมินข้อมูลเมตาของไฟล์ที่กำลังอัปโหลด ดาวน์โหลด แก้ไข หรือลบ วิธีนี้ช่วยให้คุณสร้างกฎที่ซับซ้อนและมีประสิทธิภาพซึ่งทำสิ่งต่างๆ เช่น อนุญาตให้อัปโหลดไฟล์ที่มีเนื้อหาบางประเภทเท่านั้น หรือเฉพาะไฟล์ที่มีขนาดใหญ่กว่าขนาดที่กำหนดเท่านั้นที่จะถูกลบ
กฎความปลอดภัยของ Firebase สำหรับ Cloud Storage จะให้ข้อมูลเมตาของไฟล์ในอ resource
ซึ่งมีคู่คีย์/ค่าของข้อมูลเมตาที่แสดงอยู่ในออบเจ็กต์ Cloud Storage คุณสมบัติเหล่านี้สามารถตรวจสอบได้ในคำขอ read
หรือ write
เพื่อให้แน่ใจว่าข้อมูลมีความสมบูรณ์
ในคำขอ write
(เช่น การอัปโหลด การอัปเดตข้อมูลเมตา และการลบ) นอกเหนือจากอ resource
เจกต์ทรัพยากรซึ่งมีข้อมูลเมตาของไฟล์สำหรับไฟล์ที่มีอยู่ในปัจจุบันในเส้นทางคำขอ คุณยังมีความสามารถในการใช้ออบเจกต์ request.resource
ซึ่งมีชุดย่อยของข้อมูลเมตาของไฟล์ที่จะเขียนหากอนุญาตให้เขียนได้ คุณสามารถใช้ค่าทั้งสองนี้เพื่อรับรองความถูกต้องของข้อมูลหรือบังคับใช้ข้อจำกัดของแอปพลิเคชัน เช่น ประเภทไฟล์หรือขนาด
รายการคุณสมบัติทั้งหมดในวัตถุ resource
มีอยู่ด้านล่าง:
คุณสมบัติ | พิมพ์ | คำอธิบาย |
---|---|---|
name | สตริง | ชื่อเต็มของวัตถุ |
bucket | สตริง | ชื่อของบัคเก็ตที่วัตถุนี้อยู่ |
generation | นานาชาติ | การสร้างวัตถุ Google Cloud Storage ของวัตถุนี้ |
metageneration | นานาชาติ | การสร้างเมตาของวัตถุ Google Cloud Storage ของวัตถุนี้ |
size | นานาชาติ | ขนาดของวัตถุเป็นไบต์ |
timeCreated | การประทับเวลา | การประทับเวลาที่แสดงถึงเวลาที่สร้างวัตถุ |
updated | การประทับเวลา | การประทับเวลาที่แสดงถึงเวลาที่อัปเดตอ็อบเจ็กต์ครั้งล่าสุด |
md5Hash | สตริง | แฮช MD5 ของวัตถุ |
crc32c | สตริง | แฮช crc32c ของวัตถุ |
etag | สตริง | etag ที่เกี่ยวข้องกับวัตถุนี้ |
contentDisposition | สตริง | การจัดการเนื้อหาที่เกี่ยวข้องกับวัตถุนี้ |
contentEncoding | สตริง | การเข้ารหัสเนื้อหาที่เกี่ยวข้องกับวัตถุนี้ |
contentLanguage | สตริง | ภาษาของเนื้อหาที่เกี่ยวข้องกับวัตถุนี้ |
contentType | สตริง | ประเภทเนื้อหาที่เกี่ยวข้องกับวัตถุนี้ |
metadata | แผนที่<string, string> | คู่คีย์/ค่าของข้อมูลเมตาที่กำหนดเองเพิ่มเติมที่นักพัฒนาซอฟต์แวร์ระบุ |
request.resource
มีสิ่งเหล่านี้ทั้งหมด ยกเว้น generation
, metageneration
, etag
, timeCreated
และ updated
เพิ่มประสิทธิภาพด้วย Cloud Firestore
คุณเข้าถึงเอกสารใน Cloud Firestore เพื่อประเมินเกณฑ์การให้สิทธิ์อื่นๆ ได้
เมื่อใช้ฟังก์ชัน firestore.get()
และ firestore.exists()
กฎความปลอดภัยของคุณสามารถประเมินคำขอที่เข้ามาเทียบกับเอกสารใน Cloud Firestore ฟังก์ชัน firestore.get()
และ firestore.exists()
ต่างต้องการพาธเอกสารที่ระบุโดยสมบูรณ์ เมื่อใช้ตัวแปรเพื่อสร้างเส้นทางสำหรับ firestore.get()
และ firestore.exists()
คุณต้องหลีกเลี่ยงตัวแปรอย่างชัดเจนโดยใช้ไวยากรณ์ $(variable)
ในตัวอย่างด้านล่าง เราจะเห็นกฎที่จำกัดการเข้าถึงการอ่านไฟล์สำหรับผู้ใช้ที่เป็นสมาชิกของคลับนั้นๆ
service firebase.storage { match /b/{bucket}/o { match /users/{club}/files/{fileId} { allow read: if club in firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships } } }ในตัวอย่างถัดไป เฉพาะเพื่อนของผู้ใช้เท่านั้นที่สามารถดูรูปภาพของพวกเขาได้
service firebase.storage { match /b/{bucket}/o { match /users/{userId}/photos/{fileId} { allow read: if firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id)) } } }
เมื่อคุณสร้างและบันทึกกฎความปลอดภัยของพื้นที่เก็บข้อมูลบนคลาวด์แรกที่ใช้ฟังก์ชัน Cloud Firestore เหล่านี้ คุณจะได้รับพร้อมท์ในคอนโซล Firebase หรือ Firebase CLI เพื่อเปิดใช้งานสิทธิ์ในการเชื่อมต่อผลิตภัณฑ์ทั้งสอง
คุณสามารถปิดใช้งานคุณลักษณะนี้ได้โดยลบบทบาท IAM ตามที่อธิบายไว้ใน จัดการและปรับใช้กฎความปลอดภัยของ Firebase
ตรวจสอบข้อมูล
นอกจากนี้ยังสามารถใช้กฎความปลอดภัยของ Firebase สำหรับ Cloud Storage สำหรับการตรวจสอบความถูกต้องของข้อมูล รวมถึงการตรวจสอบความถูกต้องของชื่อไฟล์และพาธ ตลอดจนคุณสมบัติของข้อมูลเมตาของไฟล์ เช่น contentType
และ size
service firebase.storage { match /b/{bucket}/o { match /images/{imageId} { // Only allow uploads of any image file that's less than 5MB allow write: if request.resource.size < 5 * 1024 * 1024 && request.resource.contentType.matches('image/.*'); } } }
ฟังก์ชั่นที่กำหนดเอง
เมื่อกฎความปลอดภัยของ Firebase มีความซับซ้อนมากขึ้น คุณอาจต้องการรวมชุดเงื่อนไขในฟังก์ชันที่คุณใช้ซ้ำได้ในชุดกฎของคุณ กฎความปลอดภัยรองรับฟังก์ชันแบบกำหนดเอง ไวยากรณ์สำหรับฟังก์ชันที่กำหนดเองจะคล้ายกับ JavaScript แต่ฟังก์ชัน Firebase Security Rules เขียนด้วยภาษาเฉพาะโดเมนซึ่งมีข้อจำกัดที่สำคัญบางประการ:
- ฟังก์ชันสามารถมีคำสั่ง
return
เดียวเท่านั้น ไม่สามารถมีตรรกะเพิ่มเติมใดๆ ตัวอย่างเช่น พวกเขาไม่สามารถดำเนินการวนซ้ำหรือเรียกใช้บริการภายนอกได้ - ฟังก์ชันสามารถเข้าถึงฟังก์ชันและตัวแปรโดยอัตโนมัติจากขอบเขตที่กำหนดไว้ ตัวอย่างเช่น ฟังก์ชันที่กำหนดภายในขอบเขต
service firebase.storage
มีสิทธิ์เข้าถึงตัวแปรresource
และสำหรับ Cloud Firestore เท่านั้น ฟังก์ชันในตัว เช่นget()
และexists()
- ฟังก์ชันอาจเรียกใช้ฟังก์ชันอื่นแต่ไม่สามารถเรียกซ้ำได้ ความลึกของ call stack ทั้งหมดจำกัดอยู่ที่ 10
- ในเวอร์ชัน
rules2
ฟังก์ชันสามารถกำหนดตัวแปรโดยใช้คำหลักlet
ฟังก์ชันสามารถมีจำนวนการผูกจำนวนเท่าใดก็ได้ แต่ต้องลงท้ายด้วยคำสั่ง return
ฟังก์ชันถูกกำหนดด้วยคีย์เวิร์ดของ function
และรับอาร์กิวเมนต์เป็นศูนย์หรือมากกว่านั้น ตัวอย่างเช่น คุณอาจต้องการรวมเงื่อนไขสองประเภทที่ใช้ในตัวอย่างด้านบนเป็นฟังก์ชันเดียว:
service firebase.storage {
match /b/{bucket}/o {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /images/{imageId} {
allow read, write: if signedInOrPublic();
}
match /mp3s/{mp3Ids} {
allow read: if signedInOrPublic();
}
}
}
การใช้ฟังก์ชันในกฎความปลอดภัยของ Firebase ทำให้สามารถบำรุงรักษาได้มากขึ้นตามความซับซ้อนของกฎที่เพิ่มขึ้น
ขั้นตอนถัดไป
หลังจากการอภิปรายเกี่ยวกับเงื่อนไขนี้ คุณมีความเข้าใจกฎที่ซับซ้อนมากขึ้น และพร้อมที่จะ:
เรียนรู้วิธีจัดการกับกรณีการใช้งานหลัก และเรียนรู้เวิร์กโฟลว์สำหรับการพัฒนา ทดสอบ และปรับใช้กฎ:
- เขียนกฎที่กล่าวถึง สถานการณ์ทั่วไป
- สร้างเสริมความรู้ของคุณโดยทบทวนสถานการณ์ที่คุณต้อง สังเกตและหลีกเลี่ยงกฎที่ไม่ปลอดภัย
- ทดสอบกฎโดยใช้ โปรแกรมจำลอง Cloud Storage และไลบรารีทดสอบกฎความปลอดภัยโดยเฉพาะ
- ตรวจสอบวิธีการที่มีให้ ปรับใช้กฎ