mirror of
https://github.com/labring/laf.git
synced 2026-01-25 16:07:45 +00:00
131 lines
3.6 KiB
Markdown
131 lines
3.6 KiB
Markdown
|
||
### 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
|
||
}
|
||
|
||
```
|
||
|
||
|
||
|