Bảo mật dữ liệu người dùng

Firebase Security Rules cho Cloud Storage tích hợp với Firebase Authentication để cung cấp với phương thức xác thực mạnh mẽ dựa trên người dùng vào 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 các thông báo xác nhận quyền sở hữu mã thông báo Firebase Authentication.

Xác thực người dùng

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 được điền bằng uid của người dùng (request.auth.uid) cũng như tuyên bố của Firebase Authentication JWT (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 được xác thực thực hiện một yêu cầu, biến request.auth sẽ là null

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

  • Công khai: bỏ qua request.auth
  • Riêng tư được xác thực: kiểm tra để đảm bảo rằng request.auth không phải là null
  • Chế độ riêng tư của người dùng: kiểm tra để đảm bảo rằng request.auth.uid khớp với đường dẫn uid
  • Nhóm riêng tư: kiểm tra các thông báo 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 báo xác nhận quyền sở hữu đã chọn, hoặc đọc siêu dữ liệu tệp để xem trường siêu dữ liệu có tồn tại không

Công khai

Bất kỳ quy tắc nào không xem xét ngữ cảnh request.auth đều có thể được coi là public, vì quy tắc này không xem xét ngữ cảnh xác thực của người dùng. Những quy tắc này có thể hữu ích khi hiển thị dữ liệu công khai như tài sản trò chơi, âm thanh tệp 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ư được xác thực

Trong một số trường hợp nhất định, bạn có thể muốn tất cả người dùng đã xác thực của vào ứng dụng của bạn chứ không phải bởi người dùng chưa được xác thực. Do request.authnull đối với tất cả người dùng chưa được xác thực, bạn chỉ cần kiểm tra biến request.auth tồn tại để yêu cầu xác thực:

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

Chế độ riêng tư của người dùng

Cho đến nay, trường hợp sử dụng phổ biến nhất cho request.auth là cung cấp người dùng có quyền chi tiết đối với tệp của họ: từ việc tải ảnh hồ sơ lên để đọc 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 làm cho một tệp do người dùng kiểm soát là một phần trong đường dẫn tệp (chẳng hạn như uid của người dùng) mà có thể được kiểm tra khi quy tắc sẽ đượ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 != null && request.auth.uid == userId;
}

Nhóm riêng tư

Một trường hợp sử dụng phổ biến khác là cấp quyền của nhóm đối với một đối tượng, chẳng hạn như cho phép nhiều thành viên trong nhóm cộng tác trên một tài liệu dùng chung. Có 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ề 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) trong siêu dữ liệu tệp

Sau khi được lưu trữ trong siêu dữ liệu tệp hoặc mã thông báo, bạn có thể tham chiếu dữ liệu này từ bên trong 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;
}

Ví dụ đầy đủ

Trình bày các trường hợp đơn giản trong bốn loại hạn chế xác thực phổ biến trong ví dụ bên dưới:

service firebase.storage {
  match /b/{bucket}/o {
    match /images {
      // Anyone can view any image (no auth, publicly readable)
      match /{allImages=**} {
        allow read;
      }

      // Only authenticated users can write to "public" images
      match /public/{imageId} {
        allow write: if request.auth != null;
      }

      // Only an individual user can write to "their" images
      match /{userId}/{imageId} {
        allow write: if request.auth.uid == userId;
      }

      // Allow a "group" of users to read/write to shared images
      // An owner metadata property on the object contains the groupId for reads
      // A custom token has been minted with a groupId property for writes
      match /{groupId}/{imageId} {
        allow read: if resource.metadata.owner == request.auth.token.groupId;
        allow write: if request.auth.token.groupId == groupId;
      }
    }
  }
}