Catch up on highlights from Firebase at Google I/O 2023. Learn more

Các quy tắc bảo mật cơ bản

Quy tắc bảo mật Firebase cho phép bạn kiểm soát quyền truy cập vào dữ liệu được lưu trữ của mình. Cú pháp quy tắc linh hoạt có nghĩa là bạn có thể tạo các quy tắc khớp với bất kỳ thứ gì, từ tất cả các lần ghi vào toàn bộ cơ sở dữ liệu đến các thao tác trên một tài liệu cụ thể.

Hướng dẫn này mô tả một số trường hợp sử dụng cơ bản hơn mà bạn có thể muốn triển khai khi thiết lập ứng dụng và bảo vệ dữ liệu của mình. Tuy nhiên, trước khi bạn bắt đầu viết quy tắc, bạn có thể muốn tìm hiểu thêm về ngôn ngữhành vi của chúng.

Để truy cập và cập nhật quy tắc của bạn, hãy làm theo các bước được nêu trong Quản lý và triển khai Quy tắc bảo mật Firebase .

Quy tắc mặc định: Chế độ bị khóa

Khi bạn tạo cơ sở dữ liệu hoặc phiên bản lưu trữ trong bảng điều khiển Firebase, bạn chọn xem Quy tắc bảo mật Firebase có hạn chế quyền truy cập vào dữ liệu của bạn ( Chế độ đã khóa ) hay cho phép mọi người truy cập ( Chế độ kiểm tra ). Trong Cloud Firestore và Cơ sở dữ liệu thời gian thực, các quy tắc mặc định cho chế độ Khóa sẽ từ chối quyền truy cập đối với tất cả người dùng. Trong Lưu trữ đám mây, chỉ người dùng được xác thực mới có thể truy cập vào bộ chứa lưu trữ.

Cửa hàng lửa trên đám mây

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Cơ sở dữ liệu thời gian thực

{
  "rules": {
    ".read": false,
    ".write": false
  }
}

Lưu trữ đám mây

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Quy luật phát triển-môi trường

Trong khi bạn đang làm việc trên ứng dụng của mình, bạn có thể muốn có quyền truy cập tương đối cởi mở hoặc không bị cản trở vào dữ liệu của mình. Bạn chỉ cần đảm bảo cập nhật Quy tắc của mình trước khi triển khai ứng dụng của mình vào sản xuất. Ngoài ra, hãy nhớ rằng nếu bạn triển khai ứng dụng của mình, thì ứng dụng đó có thể truy cập công khai — ngay cả khi bạn chưa khởi chạy ứng dụng.

Hãy nhớ rằng Firebase cho phép khách hàng truy cập trực tiếp vào dữ liệu của bạn và Quy tắc bảo mật của Firebase là biện pháp bảo vệ duy nhất ngăn chặn quyền truy cập đối với người dùng có ác ý. Việc xác định các quy tắc riêng biệt với logic sản phẩm có một số lợi thế: khách hàng không chịu trách nhiệm thực thi bảo mật, việc triển khai lỗi sẽ không ảnh hưởng đến dữ liệu của bạn và quan trọng nhất là bạn không phải dựa vào máy chủ trung gian để bảo vệ dữ liệu khỏi thế giới.

Tất cả người dùng được xác thực

Mặc dù chúng tôi khuyên bạn không nên để bất kỳ người dùng nào đã đăng nhập truy cập dữ liệu của mình, nhưng có thể hữu ích khi đặt quyền truy cập cho bất kỳ người dùng được xác thực nào trong khi bạn đang phát triển ứng dụng của mình.

Cửa hàng lửa trên đám mây

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Cơ sở dữ liệu thời gian thực

{
  "rules": {
    ".read": "auth.uid !== null",
    ".write": "auth.uid !== null"
  }
}

Lưu trữ đám mây

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Quy tắc sẵn sàng sản xuất

Khi bạn chuẩn bị triển khai ứng dụng của mình, hãy đảm bảo rằng dữ liệu của bạn được bảo vệ và quyền truy cập đó được cấp đúng cách cho người dùng của bạn. Tận dụng Xác thực để thiết lập quyền truy cập dựa trên người dùng và đọc trực tiếp từ cơ sở dữ liệu của bạn để thiết lập quyền truy cập dựa trên dữ liệu.

Cân nhắc việc viết quy tắc khi bạn cấu trúc dữ liệu của mình, vì cách bạn thiết lập quy tắc ảnh hưởng đến cách bạn hạn chế quyền truy cập vào dữ liệu ở các đường dẫn khác nhau.

Quyền truy cập chỉ dành cho chủ sở hữu nội dung

Các quy tắc này chỉ giới hạn quyền truy cập đối với chủ sở hữu đã được xác thực của nội dung. Dữ liệu chỉ có thể đọc và ghi bởi một người dùng và đường dẫn dữ liệu chứa ID của người dùng.

Khi quy tắc này hoạt động: Quy tắc này hoạt động tốt nếu dữ liệu được người dùng giữ kín — nếu người dùng duy nhất cần truy cập dữ liệu chính là người dùng đã tạo dữ liệu.

Khi quy tắc này không hoạt động: Bộ quy tắc này không hoạt động khi nhiều người dùng cần ghi hoặc đọc cùng một dữ liệu — người dùng sẽ ghi đè dữ liệu hoặc không thể truy cập dữ liệu họ đã tạo.

Để thiết lập quy tắc này: Tạo quy tắc xác nhận người dùng yêu cầu quyền truy cập để đọc hoặc ghi dữ liệu là người dùng sở hữu dữ liệu đó.

Cửa hàng lửa trên đám mây

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow only authenticated content owners access
    match /some_collection/{userId}/{documents=**} {
      allow read, write: if request.auth != null && request.auth.uid == userId
    }
  }
}

Cơ sở dữ liệu thời gian thực

{
  "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"
      }
    }
  }
}

Lưu trữ đám mây

// 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 != null && request.auth.uid == userId;
    }
  }
}

Truy cập công khai và riêng tư hỗn hợp

Quy tắc này cho phép bất kỳ ai cũng có thể đọc tập dữ liệu nhưng hạn chế khả năng tạo hoặc sửa đổi dữ liệu tại một đường dẫn nhất định chỉ dành cho chủ sở hữu nội dung đã xác thực.

Thời điểm quy tắc này hoạt động: Quy tắc này hoạt động tốt đối với các ứng dụng yêu cầu các phần tử có thể đọc công khai nhưng cần hạn chế quyền chỉnh sửa đối với chủ sở hữu của các phần tử đó. Ví dụ: ứng dụng trò chuyện hoặc blog.

Khi quy tắc này không hoạt động: Giống như quy tắc chỉ dành cho chủ sở hữu nội dung, bộ quy tắc này không hoạt động khi nhiều người dùng cần chỉnh sửa cùng một dữ liệu. Người dùng cuối cùng sẽ ghi đè lên dữ liệu của nhau.

Để thiết lập quy tắc này: Tạo quy tắc cho phép tất cả người dùng (hoặc tất cả người dùng được xác thực) có quyền truy cập đọc và xác nhận người dùng ghi dữ liệu là chủ sở hữu.

Cửa hàng lửa trên đám mây

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 create: if request.auth.uid == request.resource.data.author_uid;
      allow update, delete: if request.auth.uid == resource.data.author_uid;
    }
  }
}

Cơ sở dữ liệu thời gian thực

{
// 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"
      }
    }
  }
}

Lưu trữ đám mây

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;
    }
  }
}

Truy cập dựa trên thuộc tính và dựa trên vai trò

Để các quy tắc này hoạt động, bạn phải xác định và chỉ định các thuộc tính cho người dùng trong dữ liệu của mình. Quy tắc bảo mật Firebase kiểm tra yêu cầu đối với dữ liệu từ cơ sở dữ liệu của bạn hoặc siêu dữ liệu của tệp để xác nhận hoặc từ chối quyền truy cập.

Thời điểm quy tắc này hoạt động: Nếu bạn đang chỉ định vai trò cho người dùng, quy tắc này giúp dễ dàng giới hạn quyền truy cập dựa trên vai trò hoặc nhóm người dùng cụ thể. Ví dụ: nếu bạn đang lưu trữ điểm, bạn có thể chỉ định các mức truy cập khác nhau cho nhóm "sinh viên" (chỉ đọc nội dung của họ), nhóm "giáo viên" (đọc và viết chủ đề của họ) và nhóm "hiệu trưởng" (đọc tất cả nội dung).

Khi quy tắc này không hoạt động: Trong Cơ sở dữ liệu thời gian thực và Lưu trữ đám mây, quy tắc của bạn không thể tận dụng phương thức get() mà quy tắc Cloud Firestore có thể kết hợp. Do đó, bạn phải cấu trúc cơ sở dữ liệu hoặc siêu dữ liệu tệp của mình để phản ánh các thuộc tính bạn đang sử dụng trong các quy tắc của mình.

Để thiết lập quy tắc này: Trong Cloud Firestore, hãy bao gồm một trường trong tài liệu của người dùng mà bạn có thể đọc, sau đó cấu trúc quy tắc của bạn để đọc trường đó và cấp quyền truy cập có điều kiện. Trong Cơ sở dữ liệu thời gian thực, hãy tạo đường dẫn dữ liệu xác định người dùng ứng dụng của bạn và cấp cho họ vai trò trong nút con.

Bạn cũng có thể thiết lập xác nhận quyền sở hữu tùy chỉnh trong Xác thực rồi truy xuất thông tin đó từ biến auth.token trong bất kỳ Quy tắc bảo mật Firebase nào.

Thuộc tính và vai trò do dữ liệu xác định

Các quy tắc này chỉ hoạt động trong Cloud Firestore và Cơ sở dữ liệu thời gian thực.

Cửa hàng lửa trên đám mây

Hãy nhớ rằng bất cứ khi nào quy tắc của bạn bao gồm một lượt đọc, chẳng hạn như các quy tắc bên dưới, bạn sẽ bị tính phí cho một lượt đọc trong Cloud Firestore.

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, Check a boolean `admin` attribute
    allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
    allow read: true;

    // Alterntatively, for role-based access, assign specific roles to users
    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"
   }
  }
}

Cơ sở dữ liệu thời gian thực

{
  "rules": {
    "some_path": {
      "${subpath}": {
        //
        ".write": "root.child('users').child(auth.uid).child('role').val() === 'admin'",
        ".read": true
      }
    }
  }
}

Thuộc tính và vai trò yêu cầu tùy chỉnh

Để triển khai các quy tắc này, hãy thiết lập xác nhận quyền sở hữu tùy chỉnh trong Xác thực Firebase, sau đó tận dụng các xác nhận quyền sở hữu trong quy tắc của bạn.

Cửa hàng lửa trên đám mây

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, check for an admin claim
    allow write: if request.auth.token.admin == true;
    allow read: true;

    // Alterntatively, for role-based access, assign specific roles to users
    match /some_collection/{document} {
     allow read: if request.auth.token.reader == "true";
     allow write: if request.auth.token.writer == "true";
   }
  }
}

Cơ sở dữ liệu thời gian thực

{
  "rules": {
    "some_path": {
      "$uid": {
        // Create a custom claim for each role or group
        // you want to leverage
        ".write": "auth.uid !== null && auth.token.writer === true",
        ".read": "auth.uid !== null && auth.token.reader === true"
      }
    }
  }
}

Lưu trữ đám mây

service firebase.storage {
  // 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;
  }
}

Thuộc tính thuê nhà

Để triển khai các quy tắc này, hãy thiết lập chế độ nhiều bên thuê trong Google Cloud Identity Platform (GCIP), sau đó tận dụng đối tượng thuê trong các quy tắc của bạn. Các ví dụ sau cho phép ghi từ người dùng trong một đối tượng thuê cụ thể, ví dụ: tenant2-m6tyz

Cửa hàng lửa trên đám mây

service cloud.firestore {
  match /databases/{database}/documents {
    // For tenant-based access control, check for a tenantID
    allow write: if request.auth.token.firebase.tenant == 'tenant2-m6tyz';
    allow read: true;
  }
}

Cơ sở dữ liệu thời gian thực

{
  "rules": {
    "some_path": {
      "$uid": {
        // Only allow reads and writes if user belongs to a specific tenant
        ".write": "auth.uid !== null && auth.token.firebase.tenant === 'tenant2-m6tyz'",
        ".read": "auth.uid !== null
      }
    }
  }
}

Lưu trữ đám mây

service firebase.storage {
  // Only allow reads and writes if user belongs to a specific tenant
  match /files/{tenantId}/{fileName} {
    allow read: if request.auth != null;
    allow write: if request.auth.token.firebase.tenant == tenantId;
  }
}