使用本指南了解 Firebase 安全規則配置中的常見漏洞,檢查並更好地保護您自己的規則,並在部署變更之前測試您的變更。
如果您收到資料未得到適當保護的警報,請查看這些常見錯誤並更新任何易受攻擊的規則。
存取您的 Firebase 安全規則
若要查看現有規則,請使用 Firebase CLI 或 Firebase 控制台。確保使用相同的方法一致地編輯規則,以避免錯誤地覆寫更新。如果您不確定本機定義的規則是否反映最新更新,Firebase 控制台始終顯示 Firebase 安全性規則的最新部署版本。
若要從Firebase 控制台存取您的規則,請選擇您的項目,然後導覽至Realtime Database 、 Cloud Firestore或Storage 。進入正確的資料庫或儲存桶後,按一下規則。
若要從 Firebase CLI 存取您的規則,請前往firebase.json 檔案中記錄的規則檔案。
了解 Firebase 安全規則
Firebase 安全性規則可保護您的資料免受惡意使用者的侵害。當您在 Firebase 控制台中建立資料庫執行個體或 Cloud Storage 儲存分割區時,您可以選擇拒絕所有使用者的存取權限(鎖定模式)或授予所有使用者存取權限(測試模式)。雖然您可能在開發過程中需要更開放的配置,但請確保在部署應用程式之前花時間正確配置規則並保護資料。
當您開發應用程式並測試規則的不同配置時,請使用本機 Firebase 模擬器之一在本機開發環境中執行您的應用程式。
規則不安全的常見場景
在部署應用程式之前,應檢查並更新您預設設定的規則或最初開發應用程式時設定的規則。透過避免以下常見陷阱,確保正確保護用戶資料。
開放獲取
在設定 Firebase 專案時,您可能已設定規則以允許在開發期間進行開放存取。您可能認為您是唯一使用您的應用程式的人,但如果您部署了它,它就可以在互聯網上使用。如果您沒有對使用者進行身份驗證並配置安全規則,那麼任何猜測您的專案 ID 的人都可以竊取、修改或刪除資料。
不推薦:所有使用者都具有讀寫權限。 雲端Firestore
// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this ruleset in production; it allows
// anyone to overwrite your entire database.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
即時資料庫
{
// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this ruleset in production; it allows
// anyone to overwrite your entire database.
"rules": {
".read": true,
".write": true
}
}
雲端儲存
// Anyone can read or write to the bucket, even non-users of your app.
// Because it is shared with App Engine, this will also make
// files uploaded via App Engine public.
// Warning: This rule makes every file in your Cloud Storage bucket accessible to any user.
// Apply caution before using it in production, since it means anyone
// can overwrite all your files.
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}
|
解決方案:限制讀寫存取的規則。 建立對您的資料層次結構有意義的規則。解決這種不安全問題的常見解決方案之一是使用 Firebase 驗證來實現基於使用者的安全性。了解有關使用規則驗證使用者身分的更多資訊。 雲端Firestore 限內容所有者
service cloud.firestore {
match /databases/{database}/documents {
// Allow only authenticated content owners access
match /some_collection/{document} {
allow read, write: if request.auth != null && request.auth.uid == request.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 read: if true
allow write: if request.auth != null && request.auth.uid == request.resource.data.author_uid
}
}
}
即時資料庫限內容所有者
{
"rules": {
"some_path": {
"$uid": {
// Allow only authenticated content owners access to their data
".read": "auth !== null && auth.uid === $uid",
".write": "auth !== null && auth.uid === $uid"
}
}
}
}
公共和私人混合訪問
{
// Allow anyone to read data, but only authenticated content owners can
// make changes to their data
"rules": {
"some_path/$uid": {
".read": true,
// or ".read": "auth.uid !== null" for only authenticated users
".write": "auth.uid === $uid"
}
}
}
雲端儲存限內容所有者
// Grants a user access to a node matching their user ID
service firebase.storage {
match /b/{bucket}/o {
// Files look like: "user/<UID>/path/to/file.txt"
match /user/{userId}/{allPaths=**} {
allow read, write: if request.auth.uid == userId;
}
}
}
公共和私人混合訪問
service firebase.storage {
match /b/{bucket}/o {
// Files look like: "user/<UID>/path/to/file.txt"
match /user/{userId}/{allPaths=**} {
allow read;
allow write: if request.auth.uid == userId;
}
}
}
|
任何經過身份驗證的用戶都可以訪問
有時,規則會檢查使用者是否已登錄,但不會根據該驗證進一步限制存取。如果您的規則之一包含auth != null
,請確認您希望任何登入使用者都有權存取資料。
不建議:任何登入使用者都具有對整個資料庫的讀寫存取權限。 雲端Firestore
service cloud.firestore {
match /databases/{database}/documents {
match /some_collection/{document} {
allow read, write: if request.auth.uid != null;
}
}
}
即時資料庫
{
"rules": {
".read": "auth.uid !== null",
".write": "auth.uid !== null"
}
}
雲端儲存
// Only authenticated users can read or write to the bucket
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
|
解決方案:利用安全條件縮小存取範圍。 當您檢查身份驗證時,您可能還想使用身份驗證屬性之一來進一步限制特定使用者對特定資料集的存取。了解有關不同身份驗證屬性的更多資訊。 雲端Firestore 基於角色的訪問
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 get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Reader"
allow write: if 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
}
}
}
即時資料庫限內容所有者
{
"rules": {
"some_path": {
"$uid": {
// Allow only authenticated content owners access to their data
".read": "auth.uid === $uid",
".write": "auth.uid === $uid"
}
}
}
}
路徑描繪的訪問
{
"rules": {
"some_path/$uid": {
".write": "auth.uid === $uid",
// Create a "public" subpath in your dataset
"public": {
".read": true
// or ".read": "auth.uid !== null"
},
// Create a "private" subpath in your dataset
"private": {
".read": "auth.uid === $uid"
}
}
}
}
公共和私人混合訪問
{
// Allow anyone to read data, but only authenticated content owners can
// make changes to their data
"rules": {
"some_path/$uid": {
".read": true,
// or ".read": "auth.uid !== null" for only authenticated users
".write": "auth.uid === $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;
}
限內容所有者
// Grants a user access to a node matching their user ID
service firebase.storage {
match /b/{bucket}/o {
// Files look like: "user/<UID>/path/to/file.txt"
match /user/{userId}/{allPaths=**} {
allow read, write: if request.auth.uid == userId;
}
}
}
公共和私人混合訪問
service firebase.storage {
match /b/{bucket}/o {
// Files look like: "user/<UID>/path/to/file.txt"
match /user/{userId}/{allPaths=**} {
allow read;
allow write: if request.auth.uid == userId;
}
}
}
|
(即時資料庫)繼承規則不當
即時資料庫安全規則級聯,較淺的父路徑中的規則會覆蓋較深的子節點中的規則。當您在子節點編寫規則時,請記住它只能授予附加權限。您無法細化或撤銷對資料庫中更深路徑中的資料的存取。
不建議:在子路徑上細化規則
{
"rules": {
"foo": {
// allows read to /foo/*
".read": "data.child('baz').val() === true",
"bar": {
/* ignored, since read was allowed already */
".read": false
}
}
}
}
|
封閉訪問
在開發應用程式時,另一種常見方法是鎖定資料。通常,這表示您已關閉所有使用者的讀寫存取權限,如下所示:
雲端Firestore
// Deny read/write access to all users under any conditions
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
即時資料庫
{
"rules": {
".read": false,
".write": false
}
}
雲端儲存
// Access to files through Cloud Storage is completely disallowed.
// Files may still be accessible through App Engine or Google Cloud Storage APIs.
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if false;
}
}
}
Firebase Admin SDK 和 Cloud Functions 仍然可以存取您的資料庫。當您打算將 Cloud Firestore 或即時資料庫與 Firebase Admin SDK 結合作為僅伺服器後端時,請使用這些規則。雖然它是安全的,但您應該測試應用程式的客戶端是否可以正確檢索資料。
若要詳細了解 Cloud Firestore 安全性規則及其運作原理,請參閱 Cloud Firestore 安全性規則入門。
測試您的 Cloud Firestore 安全性法則
若要檢查應用程式的行為並驗證 Cloud Firestore 安全性規則配置,請使用Firebase 模擬器。在部署任何變更之前,使用 Cloud Firestore 模擬器在本機環境中執行和自動化單元測試。
若要在 Firebase 控制台中快速驗證 Firebase 安全性規則,請使用Firebase 規則模擬器。