跳到主要内容

编写安全规则

安全规则是一种强大的访问控制机制,允许您精确控制数据的访问权限。通过灵活的规则语法,您可以在数据库集合或存储桶上实现不同粒度的读写控制组合,确保数据安全。

默认规则

默认情况下,安全规则会拒绝所有的数据访问请求。这种"默认拒绝"的安全策略确保您的数据在未明确授权的情况下不会被访问。

{}  // 空规则对象表示拒绝所有访问

用户身份认证

当经过身份认证的用户发起请求时,系统会自动使用用户唯一标识 uid 及用户登录方式 loginType 填充 auth 变量。当未经身份验证的用户发出请求时,auth 变量值为 null

通过 auth 变量,您可以使用以下常用方式根据用户身份控制数据访问:

  • 公开访问:不判断 auth 值,允许所有用户访问
  • 仅登录用户访问:检查 auth != null,确保用户已登录
  • 用户私有数据:检查 auth.uid 是否等于资源 openid,确保用户只能访问自己的数据
  • 特定登录方式限制:检查 auth.loginType,例如限制匿名登录用户访问(auth.loginType != "ANONYMOUS"

公开访问规则

任何不考虑 auth 的规则均可被视为公开(public)规则,因为它不依赖用户的身份验证上下文。这类规则在提供公开数据(如静态资源内容、公共信息等)的场景下非常适用。

{
"read": "doc._openid != null"
}

仅对登录用户开放

在许多应用场景中,您可能希望限制只有已登录用户才能访问某些数据。例如,只有登录用户才可以查看论坛中的讨论内容或用户评论。由于所有未登录用户的 auth 变量值为 null,因此可以设置如下规则:

{
"read": "auth != null" // 只有已登录用户可以读取数据
}

所有用户可读,仅创建者可写

数据通过 _openid 字段记录当前数据的归属用户 ID:

{
"read": true, // 所有用户都可以读取
"write": "doc._openid == auth.openid || doc._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": true, // 所有用户都可以读取
"write": false // 普通用户不能写入,管理员通过云函数或控制台操作
}

仅管理员可读写

此规则适用于敏感数据,只允许管理员通过云函数或管理控制台访问:

{
"read": false, // 普通用户不能读取
"write": false // 普通用户不能写入
}

注意:设置为 false 的规则表示普通客户端无法访问,但管理员仍可通过云函数或控制台进行操作

数据验证

安全规则不仅可以控制访问权限,还可以用于数据验证。您可以根据数据库或存储分区中的现有数据,使用安全规则有条件地写入新数据。通过编写数据验证规则,您可以根据写入的新数据内容来限制写入操作,确保数据符合预期格式和业务规则。

对新数据的限制与验证

如果要对新创建的数据进行字段验证,例如,如果要拒绝创建包含 ranking 字段的所有文档(可能是为了防止用户自行设置排名),您可以在 create 条件中进行限制:

{
"read": true,
"create": "request.data.ranking == undefined", // 拒绝包含ranking字段的文档创建
"update": true // 允许更新操作
}

基于现有数据的访问控制

许多应用会将访问权限控制信息以字段形式存储在数据库文档中。安全规则可以根据这些文档数据属性来控制访问权限,实现更复杂的权限管理。

要实现基于角色的权限控制,您需要在用户数据中定义对应的角色和权限属性。安全规则会根据这些数据属性检查请求,决定是否允许或拒绝访问。

实际案例:教育系统权限控制

例如,在一个教育系统中,我们需要存储学生成绩,并向不同用户组分配不同的访问权限:

  • "学生"组只能查看自己的成绩(只读权限)
  • "教师"组可以查看和修改他们所教科目的所有学生成绩(读写权限)

用户表(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"
}

这个规则表示:

  1. 学生只能查看自己的成绩(studentID == auth.uid
  2. 教师可以查看他们所教科目的所有学生成绩
  3. 只有教师可以修改他们所教科目的成绩