编写安全规则
安全规则是一种强大的访问控制机制,允许您精确控制数据的访问权限。通过灵活的规则语法,您可以在数据库集合或存储桶上实现不同粒度的读写控制组合,确保数据安全。
默认规则
默认情况下,安全规则会拒绝所有的数据访问请求。这种"默认拒绝"的安全策略确保您的数据在未明确授权的情况下不会被访问。
{} // 空规则对象表示拒绝所有访问
用户身份认证
当经过身份认证的用户发起请求时,系统会自动使用用户唯一标识 uid
及用户登录方式 loginType
填充 auth
变量。当未经身份验证的用户发出请求时,auth
变量值为 null
。
通过 auth
变量,您可以使用以下常用方式根据用户身份控制数据访问:
- 公开访问:不判断
auth
值,允许所有用户访问 - 仅登录用户访问:检查
auth != null
,确保用户已登录 - 用户私有数据:检查
auth.uid
是否等于资源openid
,确保用户只能访问自己的数据 - 特定登录方式限制:检查
auth.loginType
,例如限制匿名登录用户访问(auth.loginType != "ANONYMOUS"
)
公开访问规则
任何不考虑 auth
的规则均可被视为公开(public
)规则,因为它不依赖用户的身份验证上下文。这类规则在提供公开数据(如静态资源内容、公共信息等)的场景下非常适用。
- 数据库
- 云存储
{
"read": "doc._openid != null"
}
{
"read": "resource.openid != null"
}
仅对登录用户开放
在许多应用场景中,您可能希望限制只有已登录用户才能访问某些数据。例如,只有登录用户才可以查看论坛中的讨论内容或用户评论。由于所有未登录用户的 auth
变量值为 null
,因此可以设置如下规则:
{
"read": "auth != null" // 只有已登录用户可以读取数据
}
所有用户可读,仅创建者可写
- 数据库
- 云存储
数据通过 _openid
字段记录当前数据的归属用户 ID:
{
"read": true, // 所有用户都可以读取
"write": "doc._openid == auth.openid || doc._openid == auth.uid" // 只有创建者可以修改
}
注意:
auth.openid
适用于微信登录方式,auth.uid
适用于非微信登录方式
{
"read": true, // 所有用户都可以读取
"write": "resource.openid == auth.openid || resource.openid == auth.uid" // 只有创建者可以修改
}
注意:
auth.openid
适用于微信登录方式,auth.uid
适用于非微信登录方式
仅创建者可读写
- 数据库
- 云存储
数据通过 _openid
字段记录当前数据的归属用户 ID:
{
"read": "doc._openid == auth.openid || doc._openid == auth.uid", // 只有创建者可以读取
"write": "doc._openid == auth.openid || doc._openid == auth.uid" // 只有创建者可以修改
}
注意:
auth.openid
适用于微信登录方式,auth.uid
适用于非微信登录方式
{
"read": "resource.openid == auth.openid || resource.openid == auth.uid", // 只有创建者可以读取
"write": "resource.openid == auth.openid || resource.openid == auth.uid" // 只有创建者可以修改
}
注意:
auth.openid
适用于微信登录方式,auth.uid
适用于非微信登录方式
所有用户可读,仅管理员可写
此规则适用于公共内容,普通用户可以查看但不能修改,只有管理员通过云函数或管理控制台才能修改:
{
"read": true, // 所有用户都可以读取
"write": false // 普通用户不能写入,管理员通过云函数或控制台操作
}
仅管理员可读写
此规则适用于敏感数据,只允许管理员通过云函数或管理控制台访问:
{
"read": false, // 普通用户不能读取
"write": false // 普通用户不能写入
}
注意:设置为
false
的规则表示普通客户端无法访问,但管理员仍可通过云函数或控制台进行操作
数据验证
安全规则不仅可以控制访问权限,还可以用于数据验证。您可以根据数据库或存储分区中的现有数据,使用安全规则有条件地写入新数据。通过编写数据验证规则,您可以根据写入的新数据内容来限制写入操作,确保数据符合预期格式和业务规则。
对新数据的限制与验证
- 数据库
- 云存储
如果要对新创建的数据进行字段验证,例如,如果要拒绝创建包含 ranking
字段的所有文档(可能是为了防止用户自行设置排名),您可以在 create
条件中进行限制:
{
"read": true,
"create": "request.data.ranking == undefined", // 拒绝包含ranking字段的文档创建
"update": true // 允许更新操作
}
对于云存储,您可以确保上传的文件都必须有归属值,且归属于当前用户:
{
"read": true, // 允许所有用户读取
"write": "resource.openid == auth.openid || resource.openid == auth.uid" // 确保文件归属于当前用户
}
基于现有数据的访问控制
许多应用会将访问权限控制信息以字段形式存储在数据库文档中。安全规则可以根据这些文档数据属性来控制访问权限,实现更复杂的权限管理。
要实现基于角色的权限控制,您需要在用户数据中定义对应的角色和权限属性。安全规则会根据这些数据属性检查请求,决定是否允许或拒绝访问。
实际案例:教育系统权限控制
例如,在一个教育系统中,我们需要存储学生成绩,并向不同用户组分配不同的访问权限:
- "学生"组只能查看自己的成绩(只读权限)
- "教师"组可以查看和修改他们所教科目的所有学生成绩(读写权限)
用户表(user
集合)可以设计如下结构:
{
userID: string, // 用户唯一ID
role: string, // 用户角色:'STUDENT'或'TEACHER'
projects: string[] // 教师所教科目列表(仅教师角色有此字段)
}
成绩表(score
集合)设计如下:
{
studentID: string, // 学生ID
project: string, // 科目名称
score: number // 分数
}
成绩表的安全规则可设置为:
{
"read": "get(`database.user.${auth.uid}`).role == 'STUDENT' && doc.studentID == auth.uid || (get(`database.user.${auth.uid}`).role == 'TEACHER' && doc.project in get(`database.user.${auth.uid}`).projects)",
"write": "get(`database.user.${auth.uid}`).role == 'TEACHER' && doc.project in get(`database.user.${auth.uid}`).projects"
}
这个规则表示:
- 学生只能查看自己的成绩(
studentID == auth.uid
) - 教师可以查看他们所教科目的所有学生成绩
- 只有教师可以修改他们所教科目的成绩