You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 19:33:17