请阅读本指南,了解 Firestore 安全规则配置中的常见漏洞,检查并更好地保护您自己的规则,并测试和部署相应更改措施。
如果您收到有关数据未得到适当保护的提醒,请查看这些常见错误并更新所有易受攻击的规则。
访问您的 Firebase 安全规则
如需查看现有规则,请使用 Firebase CLI 或 Firebase 控制台。确保始终使用同一方法修改您的规则,以避免错误地覆盖更新。如果您不能确定本地定义的规则是否反映了最新的更新,Firebase 控制台中会始终显示最近部署的 Firebase 安全规则版本。
如需从 Firebase 控制台访问您的规则,请选择您的项目,然后导航到 Realtime Database、Cloud Firestore 或 Storage。您进入正确的数据库或存储分区之后,请点击规则。
要从 Firebase CLI 访问您的规则,请转到 firebase.json 文件中记录的规则文件。
了解 Firebase 安全规则
Firebase 安全规则可保护您的数据免受恶意用户的攻击。在 Firebase 控制台中创建数据库实例或 Cloud Storage 存储分区时,您可以选择拒绝所有用户的访问权限(锁定模式),或者为所有用户授予访问权限(测试模式)。虽然您可能想要在开发期间采用更加开放的配置,但是在部署应用之前,确保花些时间正确配置规则并保护数据。
在开发应用和测试规则的不同配置时,请使用本地 Firebase 模拟器之一在本地开发环境中运行您的应用。
具有不安全规则的常见场景
您可能已经设置了默认的规则,或者在刚开始开发应用时设置了规则,但在部署应用之前,您应该检查并更新这些规则。确保避免以下常见误区,从而妥善保护用户数据的安全。
允许公众访问
在开发期间,您在设置 Firebase 项目时可能已将您的规则设置为允许公众访问。您可能认为只有您在使用自己的应用,但如果您已经部署了该应用,互联网用户就都可以使用。如果您未对用户进行身份验证并配置安全规则,则猜测出您的项目 ID 的任何人都可以窃取、篡改或删除数据。
不推荐:为所有用户提供读写权限。
Cloud 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;
}
}
}
Realtime Database
{
// 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
}
}
Cloud Storage
// 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 Authentication 实现基于用户的安全控制。详细了解如何使用规则对用户进行身份验证。
Cloud 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": "request.auth != null && request.auth.uid == $uid",
".write": "request.auth != null && request.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": "request.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>/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
,请确认您是否想让所有已登录的用户有权访问数据。
不推荐:任何登录用户都有权在您的整个数据库中读写数据。
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
match /some_collection/{document} {
allow read, write: if request.auth.uid != null;
}
}
}
Realtime Database
{
"rules": {
".read": "auth.uid != null",
".write": "auth.uid != null"
}
}
Cloud Storage
// 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;
}
}
}
|
解决方案:使用安全条件缩小访问权限范围。
在验证身份时,您可以使用某个身份验证属性来进一步限制特定用户对特定数据集的访问权限。详细了解不同的身份验证属性。
Cloud 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": "request.auth.uid == uid",
".write": "request.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": "request.auth.uid == uid"
}
}
}
Cloud 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;
}
仅限内容所有者
// 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;
}
}
}
|
(Realtime Database) 不当继承的规则
Realtime Database 规则会进行级联,即用较浅层的父路径上的规则替换较深层的子节点上的规则。在子节点上编写规则时,请注意它只能授予额外的特权。您无法在数据库的较深层路径中细化或撤消数据访问权限。
不推荐:在子路径上细化规则
{
"rules": {
"foo": {
// allows read to /foo/*
".read": "data.child('baz').val() === true",
"bar": {
/* ignored, since read was allowed already */
".read": false
}
}
}
}
|
解决方案:在宽泛的父路径中编写规则,并在子路径授予更具体的特权
如果您需要更具体地控制数据访问权限,请提供细化规则。
详细了解如何级联实时数据库规则,请参阅保护您的数据。 |
封闭式访问
在开发应用时,另一种常见方法是封锁数据。通常,这意味着您已关闭所有用户的读写权限,如下所示:
Cloud 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;
}
}
}
Realtime Database
{
"rules": {
".read": false,
".write": false
}
}
Cloud Storage
// 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 规则模拟器。