MongoDB Realm同步中如何防范跨分组数据泄露风险
核心风险本质
你遇到的越权风险根因是把权限校验的信任边界放在了客户端侧——如果同步流程允许客户端自定义传入Group ID作为分区/过滤参数,哪怕客户端代码做了严格的参数写死,逆向分析后修改请求参数就能直接绕过,只要服务端没有做文档级的归属校验,就必然会出现数据泄露。
具体配置方案
1. 内置身份字段的映射对齐
- 把Schema里
User.id字段和Realm内置的auth.user_id做强绑定,这个值是用户登录鉴权成功后由服务端自动生成、写入的,客户端没有权限篡改或自定义,从身份源上杜绝伪造用户ID的可能。
2. 配置服务端优先的文档级权限规则
所有权限校验逻辑完全由服务端执行,不采信客户端传来的任何身份声明、分组归属声明:
- User集合权限规则
读权限匹配条件直接设为:{ "id": "%{ auth.user_id }" }。也就是说无论客户端发起什么同步请求,服务端只会允许用户读取属于自己的那条User文档,其他用户的User文档完全对其不可见,从源头堵死枚举用户、关联其他用户分组的路径。
写入权限上,对groups[]这类关联字段做修改限制:仅允许服务端后台逻辑修改,客户端没有权限自行往自己的groups[]数组里添加任意Group ID,避免用户伪造归属关系越权。 - Group集合权限规则
读权限匹配条件不依赖客户端传入的Group ID参数,而是校验文档本身的归属:{ "members": "%{ auth.user_id }" }。这个逻辑的核心是:服务端收到客户端请求读取某条Group文档时,会主动比对当前登录用户的ID是否存在于该Group文档的members数组内,匹配通过才允许返回文档,不匹配直接拒绝。
哪怕客户端逆向修改代码,传入任意其他Group的ID作为请求参数,服务端校验发现当前用户不在目标Group的成员列表里,也不会返回对应数据。
3. 重构同步分区逻辑,去掉客户端自定义参数入口
- 彻底放弃“用客户端传入的Group ID做分区键值”的设计,改成基于用户ID的单用户分区模式:同步启动时的分区值固定取当前登录用户的
auth.user_id,不给客户端留自定义输入分区参数的入口。 - 这种模式下,客户端拉取数据的逻辑非常简单:登录后用自己的用户ID启动同步,服务端会按照之前配置的文档级权限规则,自动把用户有权限看到的所有数据(包括自身的User信息、所有在members列表里的Group关联信息)同步到本地,完全不需要客户端主动传Group ID去拉取分组数据。
对应Schema里的Inverse Relationship,因为用户读自己的User文档时,groups[]数组里存的Group ID会触发关联查询,服务端会自动对每个关联的Group ID做权限校验,只有用户确实在成员列表里的Group文档,才会被同步下来,不在列表里的就算ID存在于用户的groups数组里,也会被规则过滤掉。
4. 容易踩的配置坑
- 不要在Group集合的读规则里留全量开放的兜底条件,比如
{ "id": { "$exists": true } }这类写法会让所有Group文档对任意登录用户可见,直接击穿权限防线。 - 不要给客户端开放修改Group文档
members[]字段的权限,这类字段仅允许服务端后台的分组管理逻辑写入,避免用户通过篡改成员列表把自己加进其他分组越权访问。
内容的提问来源于stack exchange,提问作者daniel3223
相关产品推荐
相关产品推荐

