Sử dụng các điều kiện trong Quy tắc bảo mật của Firebase Cloud Storage

Hướng dẫn này dựa trên hướng dẫn tìm hiểu cú pháp cốt lõi của ngôn ngữ Firebase Security Rules để trình bày cách thêm điều kiện vào Firebase Security Rules cho Cloud Storage.

Thành phần chính của Cloud Storage Security Rules là điều kiện. Điều kiện là một biểu thức boolean xác định xem một thao tác cụ thể có được cho phép hay bị từ chối hay không. Đối với các quy tắc cơ bản, việc sử dụng giá trị cố định true và false làm điều kiện sẽ hoạt động rất hiệu quả. Nhưng Firebase Security Rules cho ngôn ngữ Cloud Storage cung cấp cho bạn các cách để viết những điều kiện phức tạp hơn, có thể:

  • Kiểm tra việc xác thực người dùng
  • Xác thực dữ liệu đến

Để đượ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 Cloud Storage data.

Xác thực

Firebase Security Rules cho Cloud Storage tích hợp với Firebase Authentication để cung cấp tính năng xác thực mạnh mẽ dựa trên người dùng cho Cloud Storage. Điều này cho phép kiểm soát quyền truy cập chi tiết dựa trên thông tin xác nhận quyền sở hữu của mã thông báo Firebase Authentication.

Khi người dùng đã xác thực thực hiện một yêu cầu đối với Cloud Storage, biến request.auth sẽ được điền sẵn uid của người dùng (request.auth.uid) cũng như các thông báo xác nhận quyền sở hữu của JWT Firebase Authentication (request.auth.token).

Ngoài ra, khi sử dụng phương thức xác thực tuỳ chỉnh, các thông báo xác nhận quyền sở hữu bổ sung sẽ xuất hiện trong trường request.auth.token.

Khi người dùng chưa xác thực thực hiện yêu cầu, biến request.auth sẽ là null.

Khi sử dụng dữ liệu này, có một số cách phổ biến để dùng phương thức xác thực nhằm bảo mật tệp:

  • Công khai: bỏ qua request.auth
  • Riêng tư đã xác thực: kiểm tra để đảm bảo request.auth không phải là null
  • Người dùng riêng tư: kiểm tra để đảm bảo request.auth.uid bằng với đường dẫn uid
  • Nhóm riêng tư: kiểm tra thông tin xác nhận quyền sở hữu của mã thông báo tuỳ chỉnh để khớp với thông tin xác nhận quyền sở hữu đã chọn hoặc đọc siêu dữ liệu của tệp để xem trường siêu dữ liệu có tồn tại hay không

Công khai

Bất kỳ quy tắc nào không xem xét bối cảnh request.auth đều có thể được coi là quy tắc public, vì quy tắc đó không xem xét bối cảnh xác thực của người dùng. Các quy tắc này có thể hữu ích cho việc hiển thị dữ liệu công khai như tài sản trò chơi, tệp âm thanh hoặc nội dung tĩnh khác.

// Anyone to read a public image if the file is less than 100kB
// Anyone can upload a public file ending in '.txt'
match /public/{imageId} {
  allow read: if resource.size < 100 * 1024;
  allow write: if imageId.matches(".*\\.txt");
}

Riêng tư đã xác thực

Trong một số trường hợp, bạn có thể muốn tất cả người dùng đã xác thực của ứng dụng đều xem được dữ liệu, nhưng người dùng chưa xác thực thì không. Vì biến request.auth là null đối với tất cả người dùng chưa được xác thực, nên bạn chỉ cần kiểm tra xem biến request.auth có tồn tại hay không để yêu cầu xác thực:

// Require authentication on all internal image reads
match /internal/{imageId} {
  allow read: if request.auth != null;
}

Người dùng ở chế độ riêng tư

Cho đến nay, trường hợp sử dụng phổ biến nhất cho request.auth là cung cấp cho từng người dùng quyền chi tiết đối với tệp của họ: từ việc tải ảnh hồ sơ lên cho đến việc đọc tài liệu riêng tư.

Vì các tệp trong Cloud Storage có "đường dẫn" đầy đủ đến tệp, nên tất cả những gì cần thiết để người dùng kiểm soát tệp là một phần thông tin nhận dạng người dùng duy nhất trong tiền tố tên tệp (chẳng hạn như uid của người dùng) có thể được kiểm tra khi quy tắc được đánh giá:

// Only a user can upload their profile picture, but anyone can view it
match /users/{userId}/profilePicture.png {
  allow read;
  allow write: if request.auth.uid == userId;
}

Nhóm riêng tư

Một trường hợp sử dụng phổ biến khác là cho phép quyền nhóm đối với một đối tượng, chẳng hạn như cho phép một số thành viên trong nhóm cộng tác trên một tài liệu dùng chung. Có một số phương pháp để thực hiện việc này:

  • Tạo một mã thông báo tuỳ chỉnh Firebase Authentication chứa thông tin bổ sung về một thành viên nhóm (chẳng hạn như mã nhóm)
  • Thêm thông tin về nhóm (chẳng hạn như mã nhóm hoặc danh sách uid được uỷ quyền) vào siêu dữ liệu tệp

Sau khi được lưu trữ trong mã thông báo hoặc siêu dữ liệu tệp, dữ liệu này có thể được tham chiếu từ bên trong một quy tắc:

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

Yêu cầu đánh giá

Các thao tác tải lên, tải xuống, thay đổi siêu dữ liệu và xoá được đánh giá bằng cách sử dụng request được gửi đến Cloud Storage. Ngoài mã nhận dạng duy nhất của người dùng và tải trọng Firebase Authentication trong đối tượng request.auth như mô tả ở trên, biến request chứa đường dẫn tệp nơi yêu cầu đang được thực hiện, thời gian nhận yêu cầu và giá trị resource mới nếu yêu cầu là một thao tác ghi.

Đối tượng request cũng chứa mã nhận dạng duy nhất của người dùng và tải trọng Firebase Authentication trong đối tượng request.auth. Nội dung này sẽ được giải thích thêm trong phần Bảo mật dựa trên người dùng của tài liệu.

Dưới đây là danh sách đầy đủ các thuộc tính trong đối tượng request:

Tài sản Loại Mô tả
auth <string, string> Khi người dùng đăng nhập, hãy cung cấp uid, mã nhận dạng duy nhất của người dùng và token, một bản đồ các thông báo xác nhận quyền sở hữu JWT Firebase Authentication. Nếu không, giá trị sẽ là null.
params <string, string> Bản đồ chứa các tham số truy vấn của yêu cầu.
path đường dẫn path đại diện cho đường dẫn mà yêu cầu đang được thực hiện.
resource <string, string> Giá trị tài nguyên mới, chỉ có trong các yêu cầu write.
time timestamp Dấu thời gian thể hiện thời gian của máy chủ mà yêu cầu được đánh giá.

Đánh giá tài nguyên

Khi đánh giá các quy tắc, bạn cũng nên đánh giá siêu dữ liệu của tệp đang được tải lên, tải xuống, sửa đổi hoặc xoá. Điều này cho phép bạn tạo các quy tắc phức tạp và mạnh mẽ để thực hiện những việc như chỉ cho phép tải lên các tệp có một số loại nội dung nhất định hoặc chỉ cho phép xoá các tệp lớn hơn một kích thước nhất định.

Firebase Security Rules cho Cloud Storage cung cấp siêu dữ liệu tệp trong đối tượng resource, chứa các cặp khoá/giá trị của siêu dữ liệu xuất hiện trong đối tượng Cloud Storage. Bạn có thể kiểm tra các thuộc tính này trên yêu cầu read hoặc write để đảm bảo tính toàn vẹn của dữ liệu.

Trong các yêu cầu write (chẳng hạn như tải lên, cập nhật siêu dữ liệu và xoá), ngoài đối tượng resource (chứa siêu dữ liệu tệp cho tệp hiện có tại đường dẫn yêu cầu), bạn cũng có thể sử dụng đối tượng request.resource (chứa một tập hợp con siêu dữ liệu tệp sẽ được ghi nếu cho phép ghi). Bạn có thể sử dụng hai giá trị này để đảm bảo tính toàn vẹn của dữ liệu hoặc thực thi các quy tắc ràng buộc của ứng dụng, chẳng hạn như loại tệp hoặc kích thước.

Dưới đây là danh sách đầy đủ các thuộc tính trong đối tượng resource:

Tài sản Loại Mô tả
name chuỗi Tên đầy đủ của đối tượng
bucket chuỗi Tên của bộ chứa chứa đối tượng này.
generation int Google Cloud Storage tạo đối tượng của đối tượng này.
metageneration int Google Cloud Storage object metageneration của đối tượng này.
size int Kích thước của đối tượng tính bằng byte.
timeCreated timestamp Dấu thời gian thể hiện thời điểm tạo đối tượng.
updated timestamp Dấu thời gian cho biết thời điểm gần đây nhất một đối tượng được cập nhật.
md5Hash chuỗi Hàm băm MD5 của đối tượng.
crc32c chuỗi Hàm băm crc32c của đối tượng.
etag chuỗi Etag liên kết với đối tượng này.
contentDisposition chuỗi Cách xử lý nội dung liên kết với đối tượng này.
contentEncoding chuỗi Mã hoá nội dung liên kết với đối tượng này.
contentLanguage chuỗi Ngôn ngữ nội dung liên kết với đối tượng này.
contentType chuỗi Loại nội dung liên kết với đối tượng này.
metadata <string, string> Cặp khoá/giá trị của siêu dữ liệu tuỳ chỉnh bổ sung do nhà phát triển chỉ định.

request.resource chứa tất cả các thành phần này, ngoại trừ generation, metageneration, etag, timeCreated và updated.

Làm đẹp bằng Cloud Firestore

Bạn có thể truy cập vào các tài liệu trong Cloud Firestore để đánh giá các tiêu chí uỷ quyền khác.

Bằng cách sử dụng các hàm firestore.get() và firestore.exists(), các quy tắc bảo mật của bạn có thể đánh giá các yêu cầu đến dựa trên tài liệu trong Cloud Firestore. Cả hai hàm firestore.get() và firestore.exists() đều yêu cầu đường dẫn tài liệu được chỉ định đầy đủ. Khi sử dụng các biến để tạo đường dẫn cho firestore.get() và firestore.exists(), bạn cần thoát các biến một cách rõ ràng bằng cú pháp $(variable).

Trong ví dụ bên dưới, chúng ta thấy một quy tắc hạn chế quyền đọc tệp đối với những người dùng là thành viên của các câu lạc bộ cụ thể.

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{club}/files/{fileId} {
      allow read: if club in
        firestore.get(/databases/(default)/documents/users/$(request.auth.id)).data.memberships
    }
  }
}
Trong ví dụ tiếp theo, chỉ bạn bè của người dùng mới có thể xem ảnh của họ.
service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/photos/{fileId} {
      allow read: if
        firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id))
    }
  }
}

Sau khi tạo và lưu Cloud Storage Security Rules đầu tiên sử dụng các hàm Cloud Firestore này, bạn sẽ được nhắc trong bảng điều khiển Firebase hoặc CLI Firebase để bật quyền kết nối hai sản phẩm.

Bạn có thể tắt tính năng này bằng cách xoá một vai trò IAM, như mô tả trong phần Quản lý và triển khai Firebase Security Rules.

Xác thực dữ liệu

Bạn cũng có thể dùng Firebase Security Rules cho Cloud Storage để xác thực dữ liệu, bao gồm cả việc xác thực tên và đường dẫn tệp cũng như các thuộc tính siêu dữ liệu của tệp như contentType và size.

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      // Only allow uploads of any image file that's less than 5MB
      allow write: if request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }
  }
}

Hàm tuỳ chỉnh

Khi Firebase Security Rules trở nên phức tạp hơn, bạn nên gói các nhóm điều kiện vào các hàm mà bạn có thể sử dụng lại trong bộ quy tắc của mình. Quy tắc bảo mật hỗ trợ các hàm tuỳ chỉnh. Cú pháp cho các hàm tuỳ chỉnh có phần giống với JavaScript, nhưng các hàm Firebase Security Rules được viết bằng ngôn ngữ dành riêng cho miền có một số hạn chế quan trọng:

  • Hàm chỉ có thể chứa một câu lệnh return duy nhất. Các hàm này không được chứa bất kỳ logic bổ sung nào. Ví dụ: các hàm này không thể thực thi vòng lặp hoặc gọi các dịch vụ bên ngoài.
  • Hàm có thể tự động truy cập vào các hàm và biến trong phạm vi mà chúng được xác định. Ví dụ: một hàm được xác định trong phạm vi service firebase.storage có quyền truy cập vào biến resource và chỉ đối với Cloud Firestore, các hàm tích hợp sẵn như get() và exists().
  • Các hàm có thể gọi các hàm khác nhưng không được đệ quy. Tổng độ sâu của ngăn xếp lệnh gọi được giới hạn ở mức 10.
  • Trong phiên bản rules2, các hàm có thể xác định biến bằng từ khoá let. Hàm có thể có số lượng liên kết let bất kỳ, nhưng phải kết thúc bằng câu lệnh return.

Hàm được định nghĩa bằng từ khoá function và nhận không hoặc nhiều đối số. Ví dụ: bạn có thể kết hợp hai loại điều kiện được sử dụng trong các ví dụ trên thành một hàm duy nhất:

service firebase.storage {
  match /b/{bucket}/o {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }
    match /images/{imageId} {
      allow read, write: if signedInOrPublic();
    }
    match /mp3s/{mp3Ids} {
      allow read: if signedInOrPublic();
    }
  }
}

Việc sử dụng các hàm trong Firebase Security Rules giúp bạn dễ dàng duy trì các hàm hơn khi độ phức tạp của các quy tắc tăng lên.

Các bước tiếp theo

Sau khi thảo luận về các điều kiện, bạn đã hiểu rõ hơn về Quy tắc và sẵn sàng:

Tìm hiểu cách xử lý các trường hợp sử dụng chính, cũng như quy trình phát triển, kiểm thử và triển khai Quy tắc: