Firestore规则失效:自定义账号体系下的权限配置需求
解决自定义用户名密码体系下的Firestore规则与查询问题
问题分析
当前的核心问题有两点:
- Firestore规则配置未匹配需求,也没正确适配自定义认证的凭证传递逻辑
- Flutter端仅按用户名查询,既无法完成密码校验,还存在用户信息泄露的安全风险
修正后的Firestore规则
以下规则完全满足你提出的三个权限要求,同时适配自定义认证逻辑:
service cloud.firestore { match /databases/{database}/documents { // 规则1:允许指定项目的云函数全权限访问 allow read, write: if request.headers.get('X-Project-ID') == 'project-example'; // 规则3:管理员拥有全量访问权限 match /{document=**} { allow read, write: if exists(/databases/$(database)/documents/admins/$(request.auth.uid)) && request.auth.token.username == resource.data.username && request.auth.token.password == resource.data.password; } // 规则2:普通用户仅能访问自身的users和tasks文档 match /users/{userId} { allow read, write: if request.auth.uid == userId && request.auth.token.username == resource.data.username && request.auth.token.password == resource.data.password; } match /tasks/{userId} { allow read, write: if request.auth.uid == userId && request.auth.token.username == resource.data.username && request.auth.token.password == resource.data.password; } } }
注:这里假设你通过自定义认证给请求附加了包含
uid、username、password的凭证信息,比如云函数生成的自定义Token,或者请求头中携带的验证标识。
Flutter端查询逻辑修正
直接在客户端按用户名查询存在安全隐患,且无法完成密码校验,建议通过云函数处理登录校验:
1. 编写云函数处理登录验证
// Firebase Cloud Functions代码 exports.login = functions.https.onCall(async (data, context) => { const { username, password } = data; const userRef = admin.firestore().collection('users').where('username', '==', username).limit(1); const snapshot = await userRef.get(); if (snapshot.empty) { throw new functions.https.HttpsError('not-found', '用户不存在'); } const user = snapshot.docs[0].data(); // 注意:实际项目必须用哈希算法存储密码,禁止明文存储! if (user.password !== password) { throw new functions.https.HttpsError('unauthenticated', '密码错误'); } // 返回用户ID与验证凭证,供客户端后续请求使用 return { userId: snapshot.docs[0].id, username: user.username, // 可生成自定义Token或加密凭证,用于后续请求校验 }; });
2. Flutter端调用云函数完成登录,再访问数据
// Flutter代码:调用登录云函数 final HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('login'); try { final result = await callable.call({ 'username': usernameCtrl.text.trim(), 'password': passwordCtrl.text.trim(), }); // 存储用户信息到本地(如SharedPreferences) final userId = result.data['userId']; // 后续访问用户自身数据 final userDoc = await FirebaseFirestore.instance.collection('users').doc(userId).get(); final tasksDoc = await FirebaseFirestore.instance.collection('tasks').doc(userId).get(); } on FirebaseFunctionsException catch (e) { print('登录失败:${e.message}'); }
关键注意事项
- 禁止明文存储密码:必须使用bcrypt等哈希算法存储用户密码,云函数验证时对比哈希值,避免密码泄露风险
- 自定义凭证传递:客户端登录后,需在后续Firestore请求中携带验证后的用户标识(如自定义Token、请求头字段),确保规则能正确校验用户身份
- 云函数权限控制:确保云函数的服务账号拥有Firestore的读写权限,同时规则中正确匹配项目ID
内容的提问来源于stack exchange,提问作者Lynob
相关产品推荐
相关产品推荐

