Firestore安全规则:创建用户时检查domain属性是否唯一
用Firestore安全规则实现Domain唯一性校验,替代Cloud Functions
绝对可以!Firestore的安全规则完全能帮你实现domain字段的唯一性校验,不需要再依赖Cloud Functions做先查后写的操作,这样就能彻底消除注册时的数秒延迟,同时还能避免竞态条件(比如两个请求同时创建相同domain的文档)带来的重复问题。
核心思路
Firestore安全规则的exists()函数支持结合查询条件检查集合中是否存在匹配的文档。当用户创建新文档时,我们可以通过规则校验:当前要插入的domain在整个用户集合中不存在,只有满足这个条件才允许创建操作。
具体规则示例
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // 针对用户集合的规则配置 match /users/{userId} { // 允许创建用户文档,但必须满足domain唯一+格式合法 allow create: if // 校验domain是字符串且符合指定格式(比如@xxx.com) request.resource.data.domain is string && request.resource.data.domain.matches('@.+\\.com$') && // 核心:检查集合中没有相同domain的文档 !exists(/databases/$(database)/documents/users, where: 'domain', is: request.resource.data.domain); // 以下是基础的权限控制(可根据你的需求调整) allow read: if request.auth != null && request.auth.uid == userId; allow update: if request.auth != null && request.auth.uid == userId; } } }
关键细节说明
- 规则版本要求:必须使用
rules_version = '2'或更高版本,因为带查询条件的exists()函数是在版本2中引入的。 - 原子性保障:安全规则的校验和文档写入是原子操作,不会出现Cloud Functions先查后写时的时间差问题,完全避免了重复domain的插入。
- 索引问题:对于单字段
domain的查询,Firestore会自动创建单字段索引,不需要手动额外配置复合索引。 - 格式校验(可选):规则中加入了
matches()函数校验domain格式,确保用户输入的domain符合你预期的@domain.com格式,你可以根据实际需求调整正则表达式。
额外优化建议
如果需要大小写不敏感的唯一性校验(比如@Domain.com和@domain.com视为重复),可以在用户文档中额外存储一个domainLowercase字段(值为domain的小写版本),然后在规则中检查这个字段的唯一性:
allow create: if request.resource.data.domain is string && request.resource.data.domain.matches('@.+\\.com$') && request.resource.data.domainLowercase == request.resource.data.domain.toLowerCase() && !exists(/databases/$(database)/documents/users, where: 'domainLowercase', is: request.resource.data.domainLowercase);
这样就能确保无论大小写如何,相同的domain都会被规则拦截。
内容的提问来源于stack exchange,提问作者Sayegh
相关产品推荐
相关产品推荐

