本指南以「瞭解 Firebase Security Rules 語言的核心語法」指南為基礎,說明如何在 Firebase Security Rules 中為 Cloud Storage 新增條件。
Cloud Storage Security Rules 的主要建構區塊是「條件」。條件是布林運算式,可決定是否允許或拒絕特定作業。對於基本規則,使用 true
和 false
常值做為條件就已足夠。不過,Firebase Security Rules 語言的 Cloud Storage
可讓您編寫更複雜的條件,例如:
- 檢查使用者驗證
- 驗證連入資料
驗證
Firebase Security Rules 可與 Firebase Authentication 整合,為 Cloud Storage 提供強大的使用者身分驗證功能。Cloud Storage這可根據 Firebase Authentication 符記的聲明,進行精細的存取權控管。
經過驗證的使用者對 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
變數,因此您只需要檢查 request.auth
變數是否存在,即可要求驗證:null
// 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; }
群組私密
另一個同樣常見的用途是允許物件的群組權限,例如允許多位團隊成員協作處理共用文件。您可以採取以下幾種做法:
這項資料儲存在權杖或檔案中繼資料後,即可在規則中參照:
// 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; }
申請評估
系統會使用傳送至 Cloud Storage 的 request
評估上傳、下載、中繼資料變更和刪除作業。除了使用者的專屬 ID 和上述 request.auth
物件中的 Firebase Authentication 酬載之外,request
變數還包含執行要求的檔案路徑、收到要求的時間,以及要求是否為寫入作業,如果是,則包含新的 resource
值。
request
物件也包含使用者的專屬 ID,以及 request.auth
物件中的 Firebase Authentication 酬載,這部分會在文件「以使用者為準的安全機制」一節中進一步說明。
以下列出 request
物件的所有屬性:
屬性 | 類型 | 說明 |
---|---|---|
auth |
map<string, string> | 使用者登入後,系統會提供 uid 、使用者專屬 ID,以及 token (Firebase Authentication JWT 憑證附加資訊的地圖)。否則為 null 。 |
params |
map<string, string> | 包含要求查詢參數的地圖。 |
path |
路徑 | path ,代表要求執行的路徑。 |
resource |
map<string, string> | 新的資源值,僅適用於 write 要求。 |
time |
時間戳記 | 時間戳記,代表評估要求時的伺服器時間。 |
資源評估
評估規則時,您可能也想評估上傳、下載、修改或刪除檔案的中繼資料。這可讓您建立複雜且強大的規則,例如只允許上傳特定內容類型的檔案,或只允許刪除大於特定大小的檔案。
Firebase Security Rules 的 Cloud Storage 提供 resource
物件中的檔案中繼資料,其中包含 Cloud Storage 物件中顯示的中繼資料鍵/值組合。您可以在 read
或 write
要求中檢查這些屬性,確保資料完整性。
在 write
要求 (例如上傳、中繼資料更新和刪除) 中,除了 resource
物件 (內含目前位於要求路徑的檔案中繼資料) 之外,您也可以使用 request.resource
物件,其中包含寫入作業允許時要寫入的檔案中繼資料子集。您可以使用這兩個值確保資料完整性,或強制執行檔案類型或大小等應用程式限制。
以下列出 resource
物件的所有屬性:
屬性 | 類型 | 說明 |
---|---|---|
name |
字串 | 物件的全名 |
bucket |
字串 | 這個物件所在的值區名稱。 |
generation |
int | 這個物件的Google Cloud Storage 物件產生。 |
metageneration |
int | 這個物件的 Google Cloud Storage 物件中繼資料產生次數。 |
size |
int | 物件大小 (以位元組為單位)。 |
timeCreated |
時間戳記 | 代表物件建立時間的時間戳記。 |
updated |
時間戳記 | 代表物件上次更新時間的時間戳記。 |
md5Hash |
字串 | 物件的 MD5 雜湊。 |
crc32c |
字串 | 物件的 crc32c 雜湊。 |
etag |
字串 | 與這個物件相關聯的 etag。 |
contentDisposition |
字串 | 與這個物件相關聯的內容處置。 |
contentEncoding |
字串 | 與這個物件相關聯的內容編碼。 |
contentLanguage |
字串 | 與這個物件相關聯的內容語言。 |
contentType |
字串 | 與這個物件相關聯的內容類型。 |
metadata |
map<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 函式的 Cloud Storage Security Rules 後,系統會在 Firebase 控制台或 Firebase CLI 中提示您啟用權限,以連結這兩項產品。
如要停用這項功能,請按照「管理及部署Firebase Security Rules」一文的說明移除 IAM 角色。
驗證資料
Firebase Security Rules 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 Security Rules 越來越複雜,您可能需要將條件集包裝在函式中,以便在規則集中重複使用。安全性規則支援自訂函式。自訂函式的語法與 JavaScript 有點類似,但 Firebase Security Rules 函式是以特定領域的語言編寫,因此有一些重要限制:
- 函式只能包含單一
return
陳述式。不得包含任何額外邏輯。舉例來說,他們無法執行迴圈或呼叫外部服務。 - 函式可以自動存取定義所在範圍的函式和變數。舉例來說,在
service firebase.storage
範圍內定義的函式可以存取resource
變數,而且只能存取 Cloud Firestore 的內建函式,例如get()
和exists()
。 - 函式可以呼叫其他函式,但不得遞迴。呼叫堆疊的總深度上限為 10。
- 在
rules2
版中,函式可以使用let
關鍵字定義變數。 函式可以有任意數量的 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 Security Rules 中使用函式,可讓規則更易於維護,因為規則的複雜度會不斷增加。
後續步驟
討論完條件後,您對規則的瞭解會更深入,並可開始:
瞭解如何處理核心用途,以及開發、測試及部署規則的工作流程:
- 撰寫規則來因應常見情境。
- 請參閱這篇文章,瞭解在哪些情況下必須找出並避免使用不安全的規則,進一步擴展相關知識。
- 使用 Cloud Storage 模擬器和專屬的安全性規則測試程式庫測試規則。
- 查看部署Rules的可用方法。