laf/packages/database-proxy/docs/qa-query-rules.md

3.6 KiB
Raw Permalink Blame History

Query 安全性考虑

规则为数组时

query: ["id", "status"]

query { $or: [...] }          // 这种情况可绕过数组限制 @TODO
query { "id": 0, $or: [...] } // 这种情况可绕过数组限制 @TODO

如果不用数组,是否可限定指定字段

query: {
  id: "$uid == query.id",   // 此种情况下,如果客户端不传 id则无效需指定 required = true
  status: { 
    required: true,         // 此种情况下,可强制开启
    condition: "$value==1"  
  }
}

结论: 如果不用数组,可通过 required 强制启用指定字段,但是仍然可通过 opeartor 指定。 数组需要单独处理,如果需要数组限定范围,可禁用 operator。 或者,递归遍历所有操作符内的字段,继续使用数组限定范围。 【已按此实现】

Query 规则场景

场景1: 用户数据简单查询

使用 contidion 验证器,严格验证,指定权限下限,可确定数据安全。

condition: "$uid==query.uid"

使用 query 字段约束, 非严格验证,用户若不传 uid 则不会触发该约束

query: {
  uid: "$value == $uid"
}

使用 query 验证多条件

以下规则并不是「强制」的,只有用户传了某字段,才会触发该字段验证,如需强制验证需设置 required: true

  1. 其中,如果用户不传 uid 则不会触发 uid 的约束条件。
  2. 此 query 原定是可以限定用户只能用 uid 和 status 查询,但现在存在 operator 绕过的漏洞。【已修复:递归枚举所有输入查询字段,实现了字段的限定】
query: {
  uid: "$value == $uid",
  status: { in: ['saved', 'published'], required: true},
}

使用 query 验证是否可绕过?

query: {
  created_by: {
    required: true,
    cond: "$value == $uid"
  }
}
// 问:如果用户使用 $or: [ created_by: 1, status: true] 是否能绕过以上 cond 验证,从而以 status 为依据?
// 答不能query 验证器是以规则中配置的 fields 为依据判定和取值的,以上规则 query.created_by 表达式是取不到值的。
//    即query 验证器中显式定义约束的字段,如果出现在操作符内,其值是 undefined无法通过约束所以约束有效。

场景2存在逻辑删除数据的查询

若有专用字段存储删除状态时:

默认查询未删除的数据,此写法有要求数据有 del_flag 字段且值为 0 的 data 约束,如果该文档中没有此字段,则查询不到。 且该约束并不强制用户只能访问 未删除数据,只是缺省查询未删除。 如果用户指定 del_flag 为其它值,也是可以查询的。

query: {
  del_flag: { default: 0 }
}

如果要禁止用户访问已逻辑删除的数据:

// 此方法禁止查询删除的数据,且前端必须传此字段
query: {
  del_flag: { 
    condition: "$value != 1", 
    required: true 
  }
}
// 
query: {
  del_flag: { override: 1 }
}
逻辑删除更新
// 用户可删除或恢复自己创建的数据,如果用户不修改 del_flag则不传即可不影响修改其它字段
update: {
  data: {
    del_flag: {
      cond: "$uid == query.created_by",
      in: [0,1]
    },
    otherfield: {...}
  }
}

// 禁止用户删除数据,即禁止修改 del_flag但可修改其它字段
// 只要不配置 del_field 字段的约束即可,缺省禁止更新
update: {
  data: {
    otherfield: {...}
  },
  // 或者
  data: ["otherfield1", "otherfield2"]
}

// 补充说明,若缺省 data 规则,则用户可修改所有字段
update: {
  condition: true
}