change streams 无法监控权限变更,因其仅捕获数据层 crud 事件,而 createuser 等权限操作属管理命令,不写入 oplog 且 system.* 集合被明确排除;唯一官方支持方式是启用审计日志(auditlog)并过滤 atype 字段。

直接回答:Change Streams 本身不能监控权限变更,它只捕获数据层(insert/update/delete)事件,而权限操作(如 grantRolesToUser、createUser)属于管理命令,不写入 oplog,也不触发变更流。
为什么 watch users 集合收不到权限变更事件
即使你监听的是 admin.system.users 或自建的 users 集合,也仅能捕获对该集合文档的显式 CRUD 操作——比如应用代码调用 collection.insertOne() 写入用户记录。但 MongoDB 内置的权限管理命令(db.createUser()、db.grantRolesToUser())由 admin 数据库内部机制处理,不经过用户集合的普通写入路径,因此不会产生变更流事件。
- 权限变更实际写入
admin.system.users和admin.system.roles,但这些写入受系统保护,不暴露为标准变更流事件 -
system.*集合明确被排除在变更流支持范围之外(官方文档明确列出) - 即使你绕过命令、手动向
admin.system.users插入文档,MongoDB 服务端会拒绝或忽略,因为该集合只能由内部命令维护
真正能监控权限变更的唯一方式:审计日志(auditLog)
必须启用 MongoDB 审计日志,并过滤 atype 字段。这是唯一被官方支持且稳定的权限变更可观测手段。
- 启动时必须加参数:
--auditDestination file --auditFormat JSON --auditPath /var/log/mongodb/audit.log - 确保
mongod进程对/var/log/mongodb/有写权限,否则服务启动失败 - 关键
atype值包括:"createUser"、"updateUser"、"grantRolesToUser"、"revokeRolesFromUser"、"dropAllUsersFromDatabase" - 审计日志默认不记录数据内容,只记录操作类型、用户、时间、IP、角色变更详情,适合安全合规场景
如果非要“用变更流”做近似方案:限制性适用场景
仅当你的权限模型完全脱离 MongoDB 原生机制,改用业务表(如 myapp.users、myapp.roles)自行实现时,变更流才有效。但这意味着放弃 db.auth()、SCRAM-SHA-256 等原生能力,需自行处理认证、角色继承、权限校验逻辑。
- 监听集合必须是普通业务集合(不能是
admin、local、config库下的任何集合) - 所有权限变更必须通过应用层调用
collection.updateOne()等驱动方法完成,严禁混用原生命令 - 变更流无法得知该更新是否“生效”——例如角色字段改了,但 MongoDB 不会自动 reload 权限缓存,仍需额外调用
db.runCommand({ flushRouterConfig: 1 })(分片集群)或重启连接 - 性能上无优势:审计日志是追加写,变更流需维持长连接+心跳+重试,运维成本更高
最常被忽略的一点:很多人以为开启 changeStreamPreAndPostImages 就能抓到修改前的权限状态,但它只对数据变更有效,对权限命令零作用。别在 auditLog 没开的情况下空跑变更流监听 admin 库——它根本不会出任何数据。











