構建 Cloud Firestore 安全規則

Cloud Firestore 安全規則允許您控制對數據庫中文檔和集合的訪問。靈活的規則語法允許您創建匹配任何內容的規則,從對整個數據庫的所有寫入到對特定文檔的操作。

本指南介紹了安全規則的基本語法和結構。將此語法與安全規則條件相結合以創建完整的規則集。

服務和數據庫聲明

Cloud Firestore 安全規則始終以以下聲明開頭:

service cloud.firestore {
  match /databases/{database}/documents {
    // ...
  }
}

service cloud.firestore聲明將規則範圍限定為 Cloud Firestore,防止 Cloud Firestore 安全規則與 Cloud Storage 等其他產品的規則發生衝突。

match /databases/{database}/documents聲明指定規則應匹配項目中的任何 Cloud Firestore 數據庫。目前每個項目只有一個名為(default)的數據庫。

基本讀/寫規則

基本規則由指定文檔路徑的match語句和允許讀取指定數據時詳細說明的allow表達式組成:

service cloud.firestore {
  match /databases/{database}/documents {

    // Match any document in the 'cities' collection
    match /cities/{city} {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

所有匹配語句都應該指向文檔,而不是集合。 match 語句可以指向特定文檔,如match /cities/SF或使用通配符指向指定路徑中的任何文檔,如match /cities/{city}

在上面的示例中,匹配語句使用{city}通配符語法。這意味著該規則適用於cities集合中的任何文檔,例如/cities/SF/cities/NYC 。當 match 語句中的allow表達式被計算時, city變量將解析為城市文檔名稱,例如SFNYC

粒度操作

在某些情況下, write read為更細粒度的操作很有用。例如,您的應用程序可能希望對文檔創建和刪除文檔強制執行不同的條件。或者您可能希望允許讀取單個文檔但拒絕大型查詢。

read規則可以分為getlist ,而write規則可以分為createupdatedelete

service cloud.firestore {
  match /databases/{database}/documents {
    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if <condition>;

      // Applies to queries and collection read requests
      allow list: if <condition>;
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if <condition>;

      // Applies to writes to existing documents
      allow update: if <condition>;

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

分層數據

Cloud Firestore 中的數據被組織成文檔集合,每個文檔都可以通過子集合擴展層次結構。了解安全規則如何與分層數據交互非常重要。

考慮cities集合中的每個文檔都包含一個landmarks子集合的情況。安全規則僅適用於匹配的路徑,因此在cities集合上定義的訪問控制不適用於landmarks子集合。相反,編寫顯式規則來控制對子集合的訪問:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      allow read, write: if <condition>;

        // Explicitly define rules for the 'landmarks' subcollection
        match /landmarks/{landmark} {
          allow read, write: if <condition>;
        }
    }
  }
}

嵌套match語句時,內部match語句的路徑始終相對於外部match語句的路徑。因此,以下規則集是等效的:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}
service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city}/landmarks/{landmark} {
      allow read, write: if <condition>;
    }
  }
}

遞歸通配符

如果您希望規則應用於任意深度的層次結構,請使用遞歸通配符語法{name=**} 。例如:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

當使用遞歸通配符語法時,通配符變量將包含整個匹配的路徑段,即使文檔位於深度嵌套的子集合中。例如,上面列出的規則將匹配位於/cities/SF/landmarks/coit_tower的文檔,並且document變量的值將是SF/landmarks/coit_tower

但是請注意,遞歸通配符的行為取決於規則版本。

版本 1

安全規則默認使用版本 1。在版本 1 中,遞歸通配符匹配一個或多個路徑項。它們不匹配空路徑,因此match /cities/{city}/{document=**}匹配子集合中的文檔,但不匹配cities集合中的文檔,而match /cities/{document=**}匹配cities集合和子集合。

遞歸通配符必須出現在匹配語句的末尾。

版本 2

在安全規則的版本 2 中,遞歸通配符匹配零個或多個路徑項。 match/cities/{city}/{document=**}匹配任何子集合中的文檔以及cities集合中的文檔。

您必須通過添加rules_version = '2';在您的安全規則的頂部:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{city}/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

每個 match 語句最多可以有一個遞歸通配符,但在版本 2 中,您可以將此通配符放在 match 語句中的任何位置。例如:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the songs collection group
    match /{path=**}/songs/{song} {
      allow read, write: if <condition>;
    }
  }
}

如果您使用集合組查詢,則必須使用版本 2,請參閱保護集合組查詢

重疊匹配語句

一個文檔可以匹配多個match語句。在多個allow表達式匹配請求的情況下,如果任何條件為true ,則允許訪問:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the 'cities' collection.
    match /cities/{city} {
      allow read, write: if false;
    }

    // Matches any document in the 'cities' collection or subcollections.
    match /cities/{document=**} {
      allow read, write: if true;
    }
  }
}

在上面的示例中,所有對cities集合的讀取和寫入都將被允許,因為第二條規則始終為true ,即使第一條規則始終為false

安全規則限制

使用安全規則時,請注意以下限制:

限制細節
每個請求的exists()get()getAfter()調用的最大數量
  • 10 用於單文檔請求和查詢請求。
  • 20 用於多文檔讀取、事務和批量寫入。之前的 10 個限制也適用於每個操作。

    例如,假設您創建了一個包含 3 個寫入操作的批處理寫入請求,並且您的安全規則使用 2 個文檔訪問調用來驗證每個寫入。在這種情況下,每個寫入使用其 10 個訪問調用中的 2 個,而批量寫入請求使用其 20 個訪問調用中的 6 個。

超過任一限制都會導致權限被拒絕錯誤。

某些文檔訪問調用可能會被緩存,並且緩存的調用不計入限制。

最大嵌套match語句深度10
一組嵌套match語句中允許的最大路徑長度(以路徑段為單位) 100
一組嵌套match語句中允許的最大路徑捕獲變量數20
最大函數調用深度20
函數參數的最大數量7
每個函數的最大let變量綁定數10
遞歸或循環函數調用的最大數量0(不允許)
每個請求評估的最大表達式數1,000
規則集的最大大小規則集必須遵守兩個大小限制:
  • 從 Firebase 控制台或使用firebase deploy從 CLI 發布的規則集文本源的大小限制為 256 KB。
  • 當 Firebase 處理源並使其在後端處於活動狀態時,編譯規則集的大小限制為 250 KB。

下一步