Firebase 安全規則利用靈活、強大的自定義語言,支持各種複雜性和粒度。您可以根據您的應用程序的情況制定具體或一般的規則。實時數據庫規則使用類似於 JSON 結構中的 JavaScript 的語法。 Cloud Firestore 和 Cloud Storage 規則使用基於通用表達式語言 (CEL) 的語言,該語言基於 CEL 構建,並具有支持有條件授予訪問權限的match
和allow
語句。
然而,由於這些是自定義語言,因此存在學習曲線。當您深入研究更複雜的規則時,可以使用本指南更好地理解規則語言。
選擇一個產品以了解有關其規則的更多信息。
基本結構
雲Firestore
Cloud Firestore 和 Cloud Storage 中的 Firebase 安全規則使用以下結構和語法:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
在構建規則時,理解以下關鍵概念非常重要:
- 請求:
allow
語句中調用的一個或多個方法。這些是您允許運行的方法。標準方法是:get
、list
、create
、update
和delete
。read
write
方法可以對指定的數據庫或存儲路徑進行廣泛的讀寫訪問。 - 路徑:數據庫或存儲位置,表示為 URI 路徑。
- 規則:
allow
語句,其中包含一個條件,如果該條件的計算結果為 true,則允許請求。
下面將進一步詳細描述這些概念中的每一個。
雲儲存
Cloud Firestore 和 Cloud Storage 中的 Firebase 安全規則使用以下結構和語法:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
在構建規則時,理解以下關鍵概念非常重要:
- 請求:
allow
語句中調用的一個或多個方法。這些是您允許運行的方法。標準方法是:get
、list
、create
、update
和delete
。read
write
方法可以對指定的數據庫或存儲路徑進行廣泛的讀寫訪問。 - 路徑:數據庫或存儲位置,表示為 URI 路徑。
- 規則:
allow
語句,其中包含一個條件,如果該條件的計算結果為 true,則允許請求。
下面將進一步詳細描述這些概念中的每一個。
實時數據庫
在實時數據庫中,Firebase 安全規則由 JSON 文檔中包含的類似 JavaScript 的表達式組成。
他們使用以下語法:
{
"rules": {
"<<path>>": {
// Allow the request if the condition for each method is true.
".read": <<condition>>,
".write": <<condition>>,
".validate": <<condition>>
}
}
}
該規則包含三個基本要素:
- 路徑:數據庫位置。這反映了數據庫的 JSON 結構。
- 請求:這些是規則用來授予訪問權限的方法。
read
和write
規則授予廣泛的讀取和寫入訪問權限,而validate
規則則充當輔助驗證,根據傳入或現有數據授予訪問權限。 - 條件:如果評估結果為 true,則允許請求的條件。
規則構造
雲Firestore
Cloud Firestore 和 Cloud Storage 中規則的基本元素如下:
-
service
聲明:聲明規則適用的 Firebase 產品。 -
match
塊:定義規則適用的數據庫或存儲桶中的路徑。 -
allow
語句:提供授予訪問權限的條件,按方法區分。支持的方法包括:get
、list
、create
、update
、delete
以及便捷方法read
和write
。 - 可選
function
聲明:提供組合和包裝條件以便跨多個規則使用的能力。
該service
包含一個或多個帶有allow
語句match
塊,這些允許語句提供授予請求訪問權限的條件。 request
和resource
變量可在規則條件中使用。 Firebase 安全規則語言還支持function
聲明。
語法版本
syntax
語句指示用於編寫源代碼的 Firebase 規則語言的版本。該語言的最新版本是v2
。
rules_version = '2';
service cloud.firestore {
...
}
如果未提供rules_version
語句,則將使用v1
引擎評估您的規則。
服務
service
聲明定義您的規則適用於哪個 Firebase 產品或服務。每個源文件只能包含一個service
聲明。
雲Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
雲儲存
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
如果您使用 Firebase CLI 為 Cloud Firestore 和 Cloud Storage 定義規則,則必須在單獨的文件中維護它們。
匹配
match
塊聲明一個與請求操作的路徑(傳入的request.path
)相匹配的path
模式。 match
的主體必須具有一個或多個嵌套的match
塊、 allow
語句或function
聲明。嵌套match
塊中的路徑相對於父match
塊中的路徑。
path
模式是類似目錄的名稱,可能包含變量或通配符。 path
模式允許單路徑段和多路徑段匹配。 path
中綁定的任何變量在match
範圍或聲明path
的任何嵌套範圍內都是可見的。
針對path
模式的匹配可以是部分的或完整的:
- 部分匹配:
path
模式是request.path
的前綴匹配。 - 完全匹配:
path
模式匹配整個request.path
。
當完成完全匹配時,將評估塊內的規則。當進行部分匹配時,將測試嵌套match
規則以查看是否有任何嵌套path
將完成匹配。
評估每個完整match
中的規則以確定是否允許該請求。如果任何匹配規則授予訪問權限,則允許該請求。如果沒有匹配的規則授予訪問權限,則請求將被拒絕。
// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
// Partial match.
match /example/{singleSegment} { // `singleSegment` == 'hello'
allow write; // Write rule not evaluated.
// Complete match.
match /nested/path { // `singleSegment` visible in scope.
allow read; // Read rule is evaluated.
}
}
// Complete match.
match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
allow read; // Read rule is evaluated.
}
}
如上例所示, path
聲明支持以下變量:
- 單段通配符:通過將變量括在大括號中來在路徑中聲明通配符變量:
{variable}
。該變量可以在match
語句中作為string
訪問。 - 遞歸通配符:遞歸或多段通配符匹配路徑處或路徑下方的多個路徑段。此通配符匹配您設置的位置下方的所有路徑。您可以通過在段變量末尾添加
=**
字符串來聲明它:{variable=**}
。該變量可在match
語句中作為path
對象進行訪問。
允許
match
塊包含一個或多個allow
語句。這些是你的實際規則。您可以將allow
規則應用於一種或多種方法。對於 Cloud Firestore 或 Cloud Storage, allow
語句上的條件必須評估為 true 才能批准任何傳入請求。您還可以編寫不帶條件的allow
語句,例如allow read
。但是,如果allow
語句不包含條件,則它始終允許對該方法的請求。
如果滿足該方法的任何allow
規則,則允許該請求。此外,如果更廣泛的規則授予訪問權限,則規則將授予訪問權限並忽略可能限制訪問的任何更細粒度的規則。
考慮以下示例,其中任何用戶都可以讀取或刪除自己的任何文件。更細粒度的規則僅在請求寫入的用戶擁有該文件並且該文件是 PNG 時才允許寫入。用戶可以刪除子路徑中的任何文件 - 即使它們不是 PNG - 因為之前的規則允許這樣做。
service firebase.storage {
// Allow the requestor to read or delete any resource on a path under the
// user directory.
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// Allow the requestor to create or update their own images.
// When 'request.method' == 'delete' this rule and the one matching
// any path under the user directory would both match and the `delete`
// would be permitted.
match /users/{userId}/images/{imageId} {
// Whether to permit the request depends on the logical OR of all
// matched rules. This means that even if this rule did not explicitly
// allow the 'delete' the earlier rule would have.
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
方法
每個allow
語句都包含一個方法,該方法為同一方法的傳入請求授予訪問權限。
方法 | 請求類型 |
---|---|
便捷方法 | |
read | 任何類型的讀取請求 |
write | 任何類型的寫請求 |
標準方法 | |
get | 讀取單個文檔或文件的請求 |
list | 讀取查詢和集合請求 |
create | 寫入新文檔或文件 |
update | 寫入現有數據庫文檔或更新文件元數據 |
delete | 刪除數據 |
您不能在同一match
塊中重疊讀取方法,也不能在同一path
聲明中重疊寫入方法。
例如,以下規則將失敗:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && request.auth.uid == "me";
// Overlapping write methods in the same path cause an error as well
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
功能
隨著安全規則變得越來越複雜,您可能希望將條件集包裝在可以在規則集中重複使用的函數中。安全規則支持自定義功能。自定義函數的語法有點像 JavaScript,但安全規則函數是用特定於域的語言編寫的,具有一些重要的限制:
- 函數只能包含單個
return
語句。它們不能包含任何額外的邏輯。例如,它們無法執行循環或調用外部服務。 - 函數可以自動從定義的範圍內訪問函數和變量。例如,在
service cloud.firestore
範圍內定義的函數可以訪問resource
變量和內置函數,例如get()
和exists()
。 - 函數可以調用其他函數,但不能遞歸。總調用堆棧深度限制為 20。
- 在規則版本
v2
中,函數可以使用let
關鍵字定義變量。函數最多可以有 10 個 let 綁定,但必須以 return 語句結束。
函數是使用function
關鍵字定義的,並採用零個或多個參數。例如,您可能希望將上面示例中使用的兩種類型的條件組合成一個函數:
service cloud.firestore {
match /databases/{database}/documents {
// 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 /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}
下面是一個顯示函數參數和 let 賦值的示例。 Let 賦值語句必須用分號分隔。
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
請注意isAdmin
分配如何強制執行 admins 集合的查找。對於不需要不必要的查找的惰性求值,請利用&&
(AND) 和||
的短路性質(OR) 僅當isAuthor
顯示為 true(對於&&
比較)或 false(對於||
比較)時才調用第二個函數的比較。
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
隨著規則復雜性的增加,在安全規則中使用函數可以使它們更易於維護。
雲儲存
Cloud Firestore 和 Cloud Storage 中規則的基本元素如下:
-
service
聲明:聲明規則適用的 Firebase 產品。 -
match
塊:定義規則適用的數據庫或存儲桶中的路徑。 -
allow
語句:提供授予訪問權限的條件,按方法區分。支持的方法包括:get
、list
、create
、update
、delete
以及便捷方法read
和write
。 - 可選
function
聲明:提供組合和包裝條件以便跨多個規則使用的能力。
該service
包含一個或多個帶有allow
語句match
塊,這些允許語句提供授予請求訪問權限的條件。 request
和resource
變量可在規則條件中使用。 Firebase 安全規則語言還支持function
聲明。
語法版本
syntax
語句指示用於編寫源代碼的 Firebase 規則語言的版本。該語言的最新版本是v2
。
rules_version = '2';
service cloud.firestore {
...
}
如果未提供rules_version
語句,則將使用v1
引擎評估您的規則。
服務
service
聲明定義您的規則適用於哪個 Firebase 產品或服務。每個源文件只能包含一個service
聲明。
雲Firestore
service cloud.firestore {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
雲儲存
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
如果您使用 Firebase CLI 為 Cloud Firestore 和 Cloud Storage 定義規則,則必須在單獨的文件中維護它們。
匹配
match
塊聲明一個與請求操作的路徑(傳入的request.path
)相匹配的path
模式。 match
的主體必須具有一個或多個嵌套的match
塊、 allow
語句或function
聲明。嵌套match
塊中的路徑相對於父match
塊中的路徑。
path
模式是類似目錄的名稱,可能包含變量或通配符。 path
模式允許單路徑段和多路徑段匹配。 path
中綁定的任何變量在match
範圍或聲明path
的任何嵌套範圍內都是可見的。
針對path
模式的匹配可以是部分的或完整的:
- 部分匹配:
path
模式是request.path
的前綴匹配。 - 完全匹配:
path
模式匹配整個request.path
。
當完成完全匹配時,將評估塊內的規則。當進行部分匹配時,將測試嵌套match
規則以查看是否有任何嵌套path
將完成匹配。
評估每個完整match
中的規則以確定是否允許該請求。如果任何匹配規則授予訪問權限,則允許該請求。如果沒有匹配的規則授予訪問權限,則請求將被拒絕。
// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
// Partial match.
match /example/{singleSegment} { // `singleSegment` == 'hello'
allow write; // Write rule not evaluated.
// Complete match.
match /nested/path { // `singleSegment` visible in scope.
allow read; // Read rule is evaluated.
}
}
// Complete match.
match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
allow read; // Read rule is evaluated.
}
}
如上例所示, path
聲明支持以下變量:
- 單段通配符:通過將變量括在大括號中來在路徑中聲明通配符變量:
{variable}
。該變量可以在match
語句中作為string
訪問。 - 遞歸通配符:遞歸或多段通配符匹配路徑處或路徑下方的多個路徑段。此通配符匹配您設置的位置下方的所有路徑。您可以通過在段變量末尾添加
=**
字符串來聲明它:{variable=**}
。該變量可在match
語句中作為path
對象進行訪問。
允許
match
塊包含一個或多個allow
語句。這些是你的實際規則。您可以將allow
規則應用於一種或多種方法。對於 Cloud Firestore 或 Cloud Storage, allow
語句上的條件必須評估為 true 才能批准任何傳入請求。您還可以編寫不帶條件的allow
語句,例如allow read
。但是,如果allow
語句不包含條件,則它始終允許對該方法的請求。
如果滿足該方法的任何allow
規則,則允許該請求。此外,如果更廣泛的規則授予訪問權限,則規則將授予訪問權限並忽略可能限制訪問的任何更細粒度的規則。
考慮以下示例,其中任何用戶都可以讀取或刪除自己的任何文件。更細粒度的規則僅在請求寫入的用戶擁有該文件並且該文件是 PNG 時才允許寫入。用戶可以刪除子路徑中的任何文件 - 即使它們不是 PNG - 因為之前的規則允許這樣做。
service firebase.storage {
// Allow the requestor to read or delete any resource on a path under the
// user directory.
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// Allow the requestor to create or update their own images.
// When 'request.method' == 'delete' this rule and the one matching
// any path under the user directory would both match and the `delete`
// would be permitted.
match /users/{userId}/images/{imageId} {
// Whether to permit the request depends on the logical OR of all
// matched rules. This means that even if this rule did not explicitly
// allow the 'delete' the earlier rule would have.
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
方法
每個allow
語句都包含一個方法,該方法為同一方法的傳入請求授予訪問權限。
方法 | 請求類型 |
---|---|
便捷方法 | |
read | 任何類型的讀取請求 |
write | 任何類型的寫請求 |
標準方法 | |
get | 讀取單個文檔或文件的請求 |
list | 讀取查詢和集合請求 |
create | 寫入新文檔或文件 |
update | 寫入現有數據庫文檔或更新文件元數據 |
delete | 刪除數據 |
您不能在同一match
塊中重疊讀取方法,也不能在同一path
聲明中重疊寫入方法。
例如,以下規則將失敗:
service bad.example {
match /rules/with/overlapping/methods {
// This rule allows reads to all authenticated users
allow read: if request.auth != null;
match another/subpath {
// This secondary, more specific read rule causes an error
allow get: if request.auth != null && request.auth.uid == "me";
// Overlapping write methods in the same path cause an error as well
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
功能
隨著安全規則變得越來越複雜,您可能希望將條件集包裝在可以在規則集中重複使用的函數中。安全規則支持自定義功能。自定義函數的語法有點像 JavaScript,但安全規則函數是用特定於域的語言編寫的,具有一些重要的限制:
- 函數只能包含單個
return
語句。它們不能包含任何額外的邏輯。例如,它們無法執行循環或調用外部服務。 - 函數可以自動從定義的範圍內訪問函數和變量。例如,在
service cloud.firestore
範圍內定義的函數可以訪問resource
變量和內置函數,例如get()
和exists()
。 - 函數可以調用其他函數,但不能遞歸。總調用堆棧深度限制為 20。
- 在規則版本
v2
中,函數可以使用let
關鍵字定義變量。函數最多可以有 10 個 let 綁定,但必須以 return 語句結束。
函數是使用function
關鍵字定義的,並採用零個或多個參數。例如,您可能希望將上面示例中使用的兩種類型的條件組合成一個函數:
service cloud.firestore {
match /databases/{database}/documents {
// 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 /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}
下面是一個顯示函數參數和 let 賦值的示例。 Let 賦值語句必須用分號分隔。
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
請注意isAdmin
分配如何強制執行 admins 集合的查找。對於不需要不必要的查找的惰性求值,請利用&&
(AND) 和||
的短路性質(OR) 僅當isAuthor
顯示為 true(對於&&
比較)或 false(對於||
比較)時才調用第二個函數的比較。
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
// `||` is short-circuiting; isAdmin called only if isAuthor == false.
return isAuthor || isAdmin(userId);
}
隨著規則復雜性的增加,在安全規則中使用函數可以使它們更易於維護。
實時數據庫
如上所述,實時數據庫規則包括三個基本元素:作為數據庫 JSON 結構鏡像的數據庫位置、請求類型以及授予訪問的條件。
數據庫位置
規則的結構應遵循數據庫中存儲的數據的結構。例如,在包含消息列表的聊天應用程序中,您可能擁有如下所示的數據:
{
"messages": {
"message0": {
"content": "Hello",
"timestamp": 1405704370369
},
"message1": {
"content": "Goodbye",
"timestamp": 1405704395231
},
...
}
}
您的規則應該反映該結構。例如:
{
"rules": {
"messages": {
"$message": {
// only messages from the last ten minutes can be read
".read": "data.child('timestamp').val() > (now - 600000)",
// new messages must have a string content and a number timestamp
".validate": "newData.hasChildren(['content', 'timestamp']) &&
newData.child('content').isString() &&
newData.child('timestamp').isNumber()"
}
}
}
}
如上例所示,實時數據庫規則支持$location
變量來匹配路徑段。在路徑段前面使用$
前綴將您的規則與路徑上的任何子節點相匹配。
{
"rules": {
"rooms": {
// This rule applies to any child of /rooms/, the key for each room id
// is stored inside $room_id variable for reference
"$room_id": {
"topic": {
// The room's topic can be changed if the room id has "public" in it
".write": "$room_id.contains('public')"
}
}
}
}
}
您還可以將$variable
與常量路徑名並行使用。
{
"rules": {
"widget": {
// a widget can have a title or color attribute
"title": { ".validate": true },
"color": { ".validate": true },
// but no other child paths are allowed
// in this case, $other means any key excluding "title" and "color"
"$other": { ".validate": false }
}
}
}
方法
在實時數據庫中,存在三種類型的規則。其中兩種規則類型( read
和write
)適用於傳入請求的方法。 validate
規則類型強制執行數據結構並驗證數據的格式和內容。規則在驗證.write
規則授予訪問權限後運行.validate
規則。
規則類型 | |
---|---|
。讀 | 描述是否以及何時允許用戶讀取數據。 |
。寫 | 描述是否以及何時允許寫入數據。 |
。證實 | 定義格式正確的值的外觀、是否具有子屬性以及數據類型。 |
默認情況下,如果沒有規則允許,則會拒絕路徑上的訪問。
建設條件
雲Firestore
條件是一個布爾表達式,用於確定是否應允許或拒絕特定操作。 request
和resource
變量為這些條件提供了上下文。
request
變量
request
變量包括以下字段及對應信息:
request.auth
包含來自 Firebase 身份驗證的身份驗證憑據的 JSON Web 令牌 (JWT)。 auth
令牌包含一組標準聲明以及您通過 Firebase 身份驗證創建的任何自定義聲明。詳細了解Firebase 安全規則和身份驗證。
request.method
request.method
可以是任何標準方法或自定義方法。還存在便利方法read
和write
來簡化分別適用於所有隻讀或所有隻寫標準方法的寫入規則。
request.params
request.params
包含與request.resource
沒有明確相關但可能對評估有用的任何數據。實際上,該映射對於所有標準方法都應該為空,並且對於自定義方法應該包含非資源數據。服務必須小心,不要重命名或修改作為參數呈現的任何鍵和值的類型。
request.path
request.path
是目標resource
的路徑。該路徑是相對於服務的。包含非 url 安全字符(例如/
的路徑段是 url 編碼的。
resource
變量
resource
是服務中的當前值,表示為鍵值對映射。在條件內引用resource
將導致最多從服務中讀取一次值。此查找將計入該資源的任何與服務相關的配額。對於get
請求, resource
僅計入拒絕配額。
運算符和運算符優先級
使用下表作為 Cloud Firestore 和 Cloud Storage 規則中運算符及其相應優先級的參考。
給定任意表達式a
和b
、字段f
和索引i
。
操作員 | 描述 | 關聯性 |
---|---|---|
a[i] a() af | 索引、調用、字段訪問 | 左到右 | !a -a | 一元否定 | 右到左 |
a/ba%ba*b | 乘法運算符 | 左到右 |
a+b ab | 加法算子 | 左到右 |
a>ba>=ba | 關係運算符 | 左到右 |
a in b | 存在於列表或地圖中 | 左到右 |
a is type | 類型比較,其中type 可以是 bool、int、float、number、string、list、map、timestamp、duration、path 或 latlng | 左到右 |
a==ba!=b | 比較運算符 | 左到右 | a && b | 條件與 | 左到右 |
a || b | 條件或 | 左到右 |
a ? true_value : false_value | 三元表達式 | 左到右 |
雲儲存
條件是一個布爾表達式,用於確定是否應允許或拒絕特定操作。 request
和resource
變量為這些條件提供了上下文。
request
變量
request
變量包括以下字段及對應信息:
request.auth
包含來自 Firebase 身份驗證的身份驗證憑據的 JSON Web 令牌 (JWT)。 auth
令牌包含一組標準聲明以及您通過 Firebase 身份驗證創建的任何自定義聲明。詳細了解Firebase 安全規則和身份驗證。
request.method
request.method
可以是任何標準方法或自定義方法。還存在便利方法read
和write
來簡化分別適用於所有隻讀或所有隻寫標準方法的寫入規則。
request.params
request.params
包含與request.resource
沒有明確相關但可能對評估有用的任何數據。實際上,該映射對於所有標準方法都應該為空,並且對於自定義方法應該包含非資源數據。服務必須小心,不要重命名或修改作為參數呈現的任何鍵和值的類型。
request.path
request.path
是目標resource
的路徑。該路徑是相對於服務的。包含非 url 安全字符(例如/
的路徑段是 url 編碼的。
resource
變量
resource
是服務中的當前值,表示為鍵值對映射。在條件內引用resource
將導致最多從服務中讀取一次值。此查找將計入任何與服務相關的資源配額。對於get
請求, resource
僅計入拒絕配額。
運算符和運算符優先級
使用下表作為 Cloud Firestore 和 Cloud Storage 規則中運算符及其相應優先級的參考。
給定任意表達式a
和b
、字段f
和索引i
。
操作員 | 描述 | 關聯性 |
---|---|---|
a[i] a() af | 索引、調用、字段訪問 | 左到右 | !a -a | 一元否定 | 右到左 |
a/ba%ba*b | 乘法運算符 | 左到右 |
a+b ab | 加法算子 | 左到右 |
a>ba>=ba | 關係運算符 | 左到右 |
a in b | 存在於列表或地圖中 | 左到右 |
a is type | 類型比較,其中type 可以是 bool、int、float、number、string、list、map、timestamp、duration、path 或 latlng | 左到右 |
a==ba!=b | 比較運算符 | 左到右 | a && b | 條件與 | 左到右 |
a || b | 條件或 | 左到右 |
a ? true_value : false_value | 三元表達式 | 左到右 |
實時數據庫
條件是一個布爾表達式,用於確定是否應允許或拒絕特定操作。您可以通過以下方式在實時數據庫規則中定義這些條件。
預定義變量
有許多有用的預定義變量可以在規則定義中訪問。以下是每項的簡要總結:
預定義變量 | |
---|---|
現在 | 自 Linux 紀元以來的當前時間(以毫秒為單位)。這對於驗證使用 SDK 的 firebase.database.ServerValue.TIMESTAMP 創建的時間戳特別有效。 |
根 | RuleDataSnapshot表示嘗試操作之前存在的 Firebase 數據庫中的根路徑。 |
新數據 | 表示嘗試操作後存在的數據的RuleDataSnapshot 。它包括正在寫入的新數據和現有數據。 |
數據 | 表示嘗試操作之前存在的數據的RuleDataSnapshot 。 |
$變量 | 用於表示 ids 和動態子鍵的通配符路徑。 |
授權 | 表示經過身份驗證的用戶的令牌有效負載。 |
這些變量可以在規則中的任何位置使用。例如,下面的安全規則確保寫入/foo/
節點的數據必須是小於 100 個字符的字符串:
{ "rules": { "foo": { // /foo is readable by the world ".read": true, // /foo is writable by the world ".write": true, // data written to /foo must be a string less than 100 characters ".validate": "newData.isString() && newData.val().length < 100" } } }
基於數據的規則
數據庫中的任何數據都可以在您的規則中使用。使用預定義變量root
、 data
和newData
,您可以訪問寫入事件之前或之後存在的任何路徑。
考慮這個例子,只要/allow_writes/
節點的值為true
,父節點沒有設置readOnly
標誌,並且新寫入的數據中有一個名為foo
的子節點,就允許寫入操作:
".write": "root.child('allow_writes').val() === true && !data.parent().child('readOnly').exists() && newData.child('foo').exists()"
基於查詢的規則
儘管您不能將規則用作過濾器,但您可以通過在規則中使用查詢參數來限制對數據子集的訪問。使用query.
規則中的表達式,用於根據查詢參數授予讀取或寫入訪問權限。
例如,以下基於查詢的規則使用基於用戶的安全規則和基於查詢的規則將對baskets
集合中的數據的訪問限制為僅活動用戶擁有的購物籃:
"baskets": {
".read": "auth.uid !== null &&
query.orderByChild === 'owner' &&
query.equalTo === auth.uid" // restrict basket access to owner of basket
}
以下查詢(其中包含規則中的查詢參數)將會成功:
db.ref("baskets").orderByChild("owner")
.equalTo(auth.currentUser.uid)
.on("value", cb) // Would succeed
但是,在規則中不包含參數的查詢將會失敗,並出現PermissionDenied
錯誤:
db.ref("baskets").on("value", cb) // Would fail with PermissionDenied
您還可以使用基於查詢的規則來限制客戶端通過讀取操作下載的數據量。
例如,以下規則限制僅對查詢的前 1000 個結果進行讀取訪問(按優先級排序):
messages: {
".read": "query.orderByKey &&
query.limitToFirst <= 1000"
}
// Example queries:
db.ref("messages").on("value", cb) // Would fail with PermissionDenied
db.ref("messages").limitToFirst(1000)
.on("value", cb) // Would succeed (default order by key)
以下query.
表達式可在實時數據庫安全規則中使用。
基於查詢的規則表達式 | ||
---|---|---|
表達 | 類型 | 描述 |
查詢.orderByKey 查詢.orderByPriority 查詢.orderByValue | 布爾值 | 對於按鍵、優先級或值排序的查詢為 true。否則為假。 |
查詢.orderByChild | 細繩 無效的 | 使用字符串表示子節點的相對路徑。例如, query.orderByChild === "address/zip" 。如果查詢不是按子節點排序的,則該值為 null。 |
查詢.startAt 查詢.endAt 查詢.equalTo | 細繩 數字 布爾值 無效的 | 檢索正在執行的查詢的邊界,如果沒有邊界集,則返回 null。 |
查詢.limitToFirst 查詢.limitToLast | 數字 無效的 | 檢索執行查詢的限制,如果沒有設置限制,則返回 null。 |
運營商
實時數據庫規則支持許多可用於組合條件語句中的變量的運算符。請參閱參考文檔中的完整運算符列表。
創造條件
您的實際情況將根據您想要授予的訪問權限而有所不同。規則有意提供極大程度的靈活性,因此您的應用程序的規則最終可以根據您的需要變得簡單或複雜。
有關創建簡單、可用於生產的規則的一些指導,請參閱基本安全規則。