使用指南

最近更新时间:2019-11-26 18:20:48

简介

为了保护用户的数据安全,云开发提供更灵活、可扩展、更细粒度的安全规则能力,开发者可以在云后台或者小程序开发工具上自定义安全规则,限制 C 端用户对数据库的访问权限。本文档主要介绍如何配置安全规则以及表达式的相关说明。

安全规则本身不收费,但是安全规则额外的数据访问会统计到计费中。

  • get 函数 会产生额外的数据访问。
  • 指定文档 ID 查询的所有写操作会产生一次数据访问。
说明:

  • 与之前数据库的权限设置一样,安全规则对数据库的权限控制是文档级别的访问控制,对文档的属性访问控制目前还不支持。
  • 安全规则仅限制 C 端用户的访问请求,对于开发者的请求(如通过云函数的访问请求)不做任何限制。

前提条件

  • 已在腾讯云云开发控制台 创建环境
  • 已在数据库下添加集合。

配置步骤

  1. 登录 腾讯云云开发控制台,选择已创建的“环境”。
  2. 进入左侧列表,单击左侧菜单【数据库】。
  3. 进入数据库页面,选择需要配置规则的集合。
  4. 进入集合管理页面,单击【权限设置】。
  5. 进入权限设置页面,单击页面右上角【切换到安全规则】。
  6. 进入编辑页面,填写好安全规则后,单击【确定】。
注意:

安全规则为高级的数据库权限配置,在切换到安全规则后,原本的 ACL 权限设置,将不再生效且不能切回 ACL 设置。

每个集合可以单独配置安全规则,通过json来描述安全规则配置,示例配置如下:

{
  "read": "auth.uid==doc.uid",
  "write": "doc.name=='zzz'"
}

以上 json 配置中解释如下:

  • key:指用户的操作类型。
  • value:指一个表达式。

当表达式执行结果的值是true时,用户的操作允许执行,否则,用户的操作则不被允许。

操作类型 说明 默认值
read 读文档 false
write 写文档,可以细分为 create、update、delete false
create 新建文档
update 更新文档
delete 删除文档
说明:

如果开发者没有详细指定写操作具体类型的规则时,默认读取write的规则。开发者的安全规则配置如下:

{
  "read": ".....",
  "write": "....",
  "create": "...."
}

用户的新建文档操作会读取create的对应规则,而update操作会读取write的规则。

表达式

表达式是伪代码的语句,配置的时候不能过长。

变量

全局变量

变量名 类型 说明
auth object 用户登录信息,字段说明参见下文
now number 当前时间
doc any 文档数据或查询条件

auth变量

字段名 类型 说明
loginType string 登录方式
uid string 用户唯一 ID
openid string 用户 openid,仅在微信登录方式下存在值

运算符

运算符 说明 示例 示例解释(集合查询)
== 等于 auth.uid == 'zzz' 用户的 uid 为 zzz
!= 不等于 auth.uid != 'zzz' 用户的 uid 不为 zzz
> 大于 doc.age>10 查询条件的 age 属性大于10
>= 大于等于 doc.age>=10 查询条件的 age 属性大于等于10
< 小于 doc.age>10 查询条件的 age 属性小于10
<= 小于等于 doc.age>=10 查询条件的 age 属性小于等于10
in 存在于集合中 auth.uid in ['zzz','aaa'] 用户的 uid 是['zzz','aaa']中的一个
!(xx in []) 不存在于集合中,使用 in 的方式描述 !(a in [1,2,3]) !(auth.uid in ['zzz','aaa']) 用户的 uid 不是['zzz','aaa']中的任何一个
&& auth.uid == 'zzz' && doc.age>10 用户的 uid 为 zzz 并且查询条件的 age 属性大于10
|| 或者 auth.uid == 'zzz' || doc.age>10 用户的 uid 为 zzz 或者查询条件的 age 属性大于10
. 对象元素访问符 auth.uid 用户的 uid
[] 数组访问符属性 get('database.collection_a.user')[auth.uid] == 'zzz' collection_a集合中iduser的文档,key 为用户 uid 的属性值为 zzz
说明:

比较运算符的右值必须为数值。

函数:get

目前仅支持get函数,唯一的参数必须为database.集合名称.文档id。通过访问其它文档的数据来判断用户操作是否符合安全规则。

使用示例

// 用户的权限是写在一个独立的文档 , 用一个数值表示用户的权限范围
{
  "read":"get('xxxx')[auth.uid] in [1,2,3]",
  "delete":"get('xxxx')[auth.uid] == 1 && doc.user in ['ersed','sfsdf'] "
}

限制条件

  • 一个表达式最多可以有3个get函数。
  • 最多可以访问2个不同的文档。
  • 不允许嵌套调用,例如以下示例。
    get("xxxx").prop[get("xxxxx").zzzz];

有效的查询

在实际使用的过程中,查询主要分为两种。

  • 集合查询:通过where条件的查询或者是聚合查询match限制的条件。如果是聚合搜索,只匹配第一个match的限制条件。
  • 指定文档 ID 查询:通过doc条件指定单个文档 ID。

查询条件中,如果key_openid,并且value{openid},或者keyuid,并且value{uid},则在服务端自动将 value 替换为实际的值。

集合查询

对于集合查询,查询条件必须是安全规则的子集,doc此时表示的是查询条件。这个子集是指规则上所有可能的子集,而不是实际数据的子集。

操作类型包括readupdatedelete

示例

// colleciton_a 的安全规则的配置
{
    "read":"doc.age>10"
}

// 符合安全规则
let queryRes = db.collection('colleciton_a').where({
    age:_.gt(10)
}).get()

// 不符合安全规则
let queryRes = db.collection('colleciton_a').where({
    age:_.gt(8)
}).get

// 符合安全规则
let res = await db.collection('collection_a').aggregate().match({
  age: _.gt(10)
}).project({
  age: 1
}).end()

// 不符合安全规则
let res = await db.collection('collection_a').aggregate().match({
  age: _.gt(8)
}).project({
  age: 1
}).end()

指定文档 ID 查询

对于指定文档 ID 的查询,文档的数据必须符合安全规则,doc此时表示的是文档的数据。

操作类型包括readupdatedeletecreate

操作类型 说明
create 会校验写入的数据是否符合安全规则的限制条件
readupdatedelete 安全规则包含了 doc 的限制,则会先从 db 中读取一次文档数据,然后判断是否符合安全规则。
说明:

对于update操作,只会校验存在于数据库中已有的文档数据,不会对写入的数据进行校验;同时不保证这个操作的原子性。

示例

// colleciton_a 的安全规则的配置
{
    "read":"doc.age>10"
}

// 文档id='ccc'的数据是
{
  age:12
}

// 文档id='ddd'的数据是
{
  age:8
}

// 符合安全规则
let queryRes = db.collection('colleciton_a').doc('ccc').get()

// 不符合安全规则
let queryRes = db.collection('colleciton_a').doc('ddd').get()

与权限设置对比

所有用户可读,仅创建者及管理员可写

{
  "read": true,
  "write": "doc._openid == auth.openid" // 登录方式为微信
  "write": "doc._openid == auth.uid" // 登录方式为非微信
}

仅创建者及管理员可读写

{
  "read": false,
  "write": "doc._openid == auth.openid" //登录方式为微信
  "write": "doc._openid == auth.uid" // 登录方式为非微信
}

所有用户可读,仅管理员可写

{
  "read": true,
  "write": false
}

仅管理员可读写

{
  "read": false,
  "write": false
}

更多详情示例请参考 使用示例