修正不安全的規則

請參閱本指南,瞭解 Firestore 安全性規則設定的常見安全漏洞、檢查並加強保護自己的規則,以及在部署變更前進行測試。

如果收到警示,指出原生模式的 Firestore 資料庫未妥善保護,您可以修改及測試 Firestore 安全性規則,解決安全漏洞。

如要查看現有的安全性規則,請前往 Firebase 控制台的「規則」分頁

瞭解 Firestore 安全性規則

Firestore 安全性規則可保護資料免於惡意使用者侵擾。在 Firebase 控制台中建立的任何 Firestore (Native Mode) 執行個體,預設規則都會拒絕所有使用者存取。如要開發應用程式及存取資料庫,您需要修改這些規則,並考慮在開發環境中授予所有使用者全面存取權。不過,在將應用程式部署至正式環境之前,請花時間正確設定規則並保護資料。

開發應用程式並測試規則的不同設定時,請使用 Firestore 原生模式模擬器,在本機開發環境中執行應用程式。

安全性偏低的規則常見情境

如果您預設或在最初使用原生模式開發應用程式時設定了 Firestore 安全性規則,請務必在部署應用程式前檢查並更新這些規則,確保使用者資料受到妥善保護,避免發生下列常見錯誤。

公開存取

設定原生模式的 Firestore 時,您可能已將規則設為在開發期間允許開放存取。您可能以為只有自己會使用應用程式,但只要部署應用程式,網路上任何人都能存取。如果您未驗證使用者身分及設定安全規則,任何猜出專案 ID 的人都能竊取、修改或刪除資料。

不建議:所有使用者都具備讀寫權限。
// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this rule set in production; it allows
// anyone to overwrite your entire database.

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}
解決方案:限制讀寫權限的規則。

建立符合資料階層的規則。其中一項常見的做法是建立以使用者為基礎的安全防護機制,並搭配使用 Firebase 驗證功能。進一步瞭解如何使用規則驗證使用者

僅限內容擁有者

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow only authenticated content owners access
    match /some_collection/{document} {
      // Allow reads and deletion if the current user owns the existing document
      allow read, delete: if request.auth.uid == resource.data.author_uid;
      // Allow creation if the current user owns the new document
      allow create: if request.auth.uid == request.resource.data.author_uid;
      // Allow updates by the owner, and prevent change of ownership
      allow update: if request.auth.uid == request.resource.data.author_uid
                    && request.auth.uid == resource.data.author_uid;

    }
  }
}
  

混合使用公開和私人存取權

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow public read access, but only content owners can write
    match /some_collection/{document} {
      // Allow public reads
      allow read: if true
      // Allow creation if the current user owns the new document
      allow create: if request.auth.uid == request.resource.data.author_uid;
      // Allow updates by the owner, and prevent change of ownership
      allow update: if request.auth.uid == request.resource.data.author_uid
                    && request.auth.uid == resource.data.author_uid;
      // Allow deletion if the current user owns the existing document
      allow delete: if request.auth.uid == resource.data.author_uid;
    }
  }
}
  

任何已驗證的使用者都能存取

有時,Firestore 安全性規則會檢查使用者是否已登入,但不會根據該驗證進一步限制存取權。如果其中一項規則包含 auth != null,請確認您要允許任何已登入的使用者存取資料。

不建議:任何登入的使用者都能讀取及寫入整個資料庫。
service cloud.firestore {
  match /databases/{database}/documents {
    match /some_collection/{document} {
      allow read, write: if request.auth != null;
    }
  }
}
解決方案:使用安全條件縮減存取權。

檢查驗證時,您可能也會想使用其中一個驗證屬性,進一步限制特定使用者存取特定資料集。進一步瞭解如何新增安全性條件以角色為基礎的存取權

角色型存取權

service cloud.firestore {
  match /databases/{database}/documents {
    // Assign roles to all users and refine access based on user roles
    match /some_collection/{document} {
     allow read: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Reader"
     allow write: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Writer"

     // Note: Checking for roles in your database using `get` (as in the code
     // above) or `exists` carry standard charges for read operations.
    }
  }
}

以屬性為準的存取權

// Give each user in your database a particular attribute
// and set it to true/false
// Then, use that attribute to grant access to subsets of data
// For example, an "admin" attribute set
// to "true" grants write access to data

service cloud.firestore {
  match /databases/{database}/documents {
    match /collection/{document} {
      allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
      allow read: true;
    }
  }
}
  

混合使用公開和私人存取權

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow public read access, but only content owners can write
    match /some_collection/{document} {
      allow read: if true
      allow write: if request.auth.uid == request.resource.data.author_uid
    }
  }
}
  

未經驗證電子郵件地址的存取權

有時,Firestore 安全性規則會檢查使用者的電子郵件是否屬於特定網域。雖然這通常是不錯的做法,但使用者收到驗證電子郵件並執行額外步驟前,系統不會在登入期間驗證電子郵件。請務必驗證電子郵件地址確實屬於使用者。

不建議:任何使用者都能以任意電子郵件地址登入。
service cloud.firestore {
  match /databases/{database}/documents {
    // Allow access based on email domain
    match /some_collection/{document} {
     allow read: if request.auth != null
                 && request.auth.email.endsWith('@example.com')
    }
  }
}
解決方案:縮小存取範圍,僅限已驗證的電子郵件。

驗證電子郵件

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow access based on email domain
    match /some_collection/{document} {
     allow read: if request.auth != null
                 && request.auth.email_verified
                 && request.auth.email.endsWith('@example.com')
    }
  }
}

封閉測試

開發應用程式時,另一種常見做法是鎖定資料。通常這表示您已對所有使用者關閉讀取和寫入存取權,如下所示:

// Deny read/write access to all users under any conditions
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Firebase Admin SDK 和 Cloud Functions 仍可存取資料庫。如果您打算搭配使用 Firebase Admin SDK,將 Firestore 原生模式做為僅限伺服器的後端,請使用這些規則。雖然安全無虞,但您應測試應用程式的用戶端是否能正確擷取資料。

如要進一步瞭解 Firestore 安全性規則及其運作方式,請參閱「開始使用 Firestore 安全性規則」。

檢查 Firestore 安全性規則

如要檢查應用程式的行為並驗證 Firestore 安全性規則設定,請使用 Firestore 原生模式模擬器。在部署任何變更之前,請先使用 Firestore 原生模式模擬器在本機環境中執行及自動化單元測試。

如要在 Firebase 控制台中快速測試更新後的 Firestore 安全性規則,請使用規則遊樂場工具。

  1. 如要開啟規則遊樂場,請按一下「規則」分頁中的「規則遊樂場」
  2. 在「規則遊樂場」設定中,選取測試選項,包括:
    • 測試讀取或寫入作業
    • 資料庫中的特定「位置」,以路徑形式表示
    • 驗證類型:未通過驗證、已通過驗證的匿名使用者,或特定使用者 ID
    • 規則明確參照的文件專屬資料 (例如,規則要求必須有特定欄位,才能允許寫入)
  3. 按一下「執行」,然後在規則視窗上方的橫幅中查看結果。