Quy tắc bảo mật cơ bản

Firebase Security Rules cho phép bạn kiểm soát quyền truy cập vào dữ liệu đã lưu trữ. Cú pháp quy tắc linh hoạt có nghĩa là bạn có thể tạo các quy tắc phù hợp với mọi thứ, từ tất cả các lượt ghi vào toàn bộ cơ sở dữ liệu cho đế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 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ắt đầu viết quy tắc, bạn nên tìm hiểu thêm về ngôn ngữ viết quy tắc và hành vi của quy tắc.

Để truy cập và cập nhật các quy tắc, hãy làm theo các bước được nêu trong bài viết Quản lý và triển khai Firebase Security Rules.

Để được trợ giúp AI, hãy sao chép câu lệnh bên dưới vào tác nhân lập trình AI (như Gemini trong Android Studio, Antigravity, Claude Code, Codex và Cursor). Bạn có thể tuỳ chỉnh câu lệnh và lặp lại với tác nhân của mình. Truy cập vào trang Kỹ năng của tác nhân Firebase để biết thông tin chi tiết về cách cài đặt.

Help me use Firebase in my app.
1. Make sure that **Firebase agent skills** are installed and updated. For Claude Code, Codex, or Cursor agents, help me install the Firebase plugin. For other agents, run `npx skills add firebase/agent-skills`. Always try to use **Firebase agent skills** for Firebase-related tasks.
2. Help me write, validate, and deploy Firebase Security Rules to protect my app's data.

Quy tắc mặc định: Chế độ khoá

Khi tạo một cơ sở dữ liệu hoặc thực thể lưu trữ trong bảng điều khiển Firebase, bạn chọn xem Firebase Security Rules có hạn chế quyền truy cập vào dữ liệu của bạn (Chế độ khoá) hay cho phép mọi người truy cập (Chế độ kiểm thử). Trong Cloud Firestore và Realtime Database, các quy tắc mặc định cho Chế độ khoá sẽ từ chối quyền truy cập của tất cả người dùng. Trong Cloud Storage, chỉ người dùng đã xác thực mới có thể truy cập vào các bộ chứa lưu trữ.

Cloud Firestore

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

Realtime Database

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

Cloud Storage

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

Quy tắc về môi trường phát triển

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

Hãy nhớ rằng Firebase cho phép ứng dụng khách truy cập trực tiếp vào dữ liệu của bạn và Firebase Security Rules là biện pháp bảo vệ duy nhất giúp chặn quyền truy cập của người dùng độc hại. Việc xác định các quy tắc tách biệt với logic sản phẩm có một số lợi ích: ứng dụng khách không chịu trách nhiệm thực thi bảo mật, việc triển khai có 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 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 đã xác thực

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

Cloud Firestore

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

Realtime Database

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

Cloud Storage

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

Quy tắc sẵn sàng phát hành công khai

Khi bạn chuẩn bị triển khai ứng dụng, hãy đảm bảo dữ liệu của bạn được bảo vệ và người dùng được cấp quyền truy cập đúng cách. Sử dụng Authentication để 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 để thiết lập quyền truy cập dựa trên dữ liệu.

Hãy cân nhắc việc viết quy tắc khi bạn cấu trúc dữ liệu, vì cách bạn thiết lập quy tắc sẽ ả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ỉ cho phép chủ sở hữu đã xác thực của nội dung truy cập. Chỉ một người dùng có thể đọc và ghi dữ liệu, đồng thời đường dẫn dữ liệu chứa mã nhận dạng của người dùng.

Trường hợp áp dụng quy tắc này: Quy tắc này hoạt động hiệu quả nếu dữ liệu được tách riêng theo người dùng, tức là người dùng duy nhất cần truy cập vào dữ liệu cũng chính là người dùng đã tạo dữ liệu đó.

Trường hợp 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 vào dữ liệu mà họ đã tạo.

Cách thiết lập quy tắc này: Tạo một quy tắc xác nhận rằng 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 đó.

Cloud Firestore

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

Realtime Database

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

Cloud Storage

// Grants a user access to a node matching their user ID
service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/file.txt"
    match /user/{userId}/{fileName} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

Quyền truy cập kết hợp công khai và riêng tư

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

Trường hợp áp dụng quy tắc này: Quy tắc này hoạt động hiệu quả đối với những ứ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.

Trường hợp 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 sẽ ghi đè dữ liệu của nhau.

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

Cloud Firestore

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

Realtime Database

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

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/file.txt"
    match /user/{userId}/{fileName} {
      allow read;
      allow write: if request.auth.uid == userId;
    }
  }
}

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

Để 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. Firebase Security Rules kiểm tra yêu cầu dựa trên dữ liệu từ cơ sở dữ liệu 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.

Trường hợp áp dụng quy tắc này: Nếu bạn đang chỉ định vai trò cho người dùng, thì quy tắc này sẽ giúp bạn 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 đang lưu trữ điểm, bạn có thể chỉ định các cấp truy cập khác nhau cho nhóm "học viên" (chỉ đọc nội dung của họ), nhóm "giáo viên" (đọc và viết trong môn học của họ) và nhóm "hiệu trưởng" (đọc tất cả nội dung).

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

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

Bạn cũng có thể thiết lập các thông báo tuỳ chỉnh trong Authentication, sau đó truy xuất thông tin đó từ biến auth.token trong bất kỳ Firebase Security Rules 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à Realtime Database.

Cloud Firestore

Xin lưu ý rằng bất cứ khi nào quy tắc của bạn có thao tác đọc, chẳng hạn như các quy tắc bên dưới, bạn sẽ bị tính phí cho thao tác đọ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"
   }
  }
}

Realtime Database

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

Thuộc tính và vai trò của thông báo xác nhận tuỳ 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 tuỳ chỉnh trong Firebase Authentication, sau đó sử dụng các xác nhận quyền sở hữu trong quy tắc của bạn.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, check for an administrator 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";
   }
  }
}

Realtime Database

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

Cloud Storage

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 đa người dùng trong Google Cloud Identity Platform (GCIP) rồi sử dụng người dùng trong các quy tắc của bạn. Các ví dụ sau đây cho phép người dùng ghi dữ liệu trong một đối tượng thuê cụ thể, chẳng hạn như tenant2-m6tyz

Cloud Firestore

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

Realtime Database

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

Cloud Storage

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