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

如何实现登录用户仅查看自身信息?附Flutter+Firebase示例代码

实现登录用户仅查看自身笔记/待办的解决方案

你的问题核心在于没有为笔记/待办数据关联当前登录用户的唯一标识,且查询逻辑未做用户隔离,导致数据查询范围覆盖全部用户内容,出现跨用户查看的异常。以下是具体解决步骤及示例代码:


1. 为数据添加用户关联标识

每个笔记/待办文档必须存储当前登录用户的uid(Firebase Auth生成的唯一用户ID,比邮箱更安全),以此区分数据归属。

修改注册逻辑(优化用户信息存储)

在现有_register方法中,建议存储用户uid而非明文密码(Firebase Auth已管理密码,明文存储有安全风险):

Future<void> _register() async {
  try {
    UserCredential userCredential = await firebaseAuth.createUserWithEmailAndPassword(
      email: email.text, 
      password: password.text
    );
    // 获取用户唯一uid
    String userId = userCredential.user!.uid;
    // 存储用户基础信息
    await fireStore.collection("todo_user").doc(userId).set({
      "email": email.text,
      "uid": userId
    });
  } on FirebaseAuthException catch (e) {
    if (e.code == 'weak-password') {
      print('密码强度不足');
    } else if (e.code == 'email-already-in-use') {
      print('该邮箱已注册');
    }
  } catch (e) {
    print(e);
  }
}

2. 添加笔记时关联当前用户uid

创建笔记文档时,必须插入当前登录用户的uid,确保数据归属正确:

Future<void> addNote(String noteContent) async {
  // 获取当前登录用户
  User? currentUser = firebaseAuth.currentUser;
  if (currentUser == null) {
    // 用户未登录,可跳转登录页或提示
    return;
  }
  
  await fireStore.collection("notes").add({
    "content": noteContent,
    "userId": currentUser.uid, // 关联当前用户标识
    "createdAt": FieldValue.serverTimestamp()
  });
}

3. 查询仅当前用户的笔记

获取笔记列表时,通过where条件过滤出属于当前登录用户的文档:

Stream<QuerySnapshot> getUserNotes() {
  User? currentUser = firebaseAuth.currentUser;
  if (currentUser == null) {
    // 返回空流或处理未登录状态
    return const Stream.empty();
  }
  // 仅查询当前用户的笔记
  return fireStore.collection("notes")
    .where("userId", isEqualTo: currentUser.uid)
    .orderBy("createdAt", descending: true)
    .snapshots();
}

在UI中使用该Stream展示数据:

@override
Widget build(BuildContext context) {
  return StreamBuilder<QuerySnapshot>(
    stream: getUserNotes(),
    builder: (context, snapshot) {
      if (snapshot.hasError) {
        return const Text('加载出错');
      }
      if (snapshot.connectionState == ConnectionState.waiting) {
        return const CircularProgressIndicator();
      }
      // 构建笔记列表
      return ListView(
        children: snapshot.data!.docs.map((doc) {
          Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
          return ListTile(
            title: Text(data["content"]),
            subtitle: Text(data["createdAt"]?.toDate().toString() ?? ""),
          );
        }).toList(),
      );
    },
  );
}

4. 设置Firestore安全规则(关键,防止非法访问)

即使客户端做了逻辑过滤,仍需通过Firestore安全规则限制用户仅能访问自身数据,避免恶意客户端绕过逻辑:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 限制用户仅能读写自己的笔记
    match /notes/{note} {
      allow read, write: if request.auth != null && request.auth.uid == resource.data.userId;
    }
    // 限制用户仅能读写自己的账户信息
    match /todo_user/{user} {
      allow read, write: if request.auth != null && request.auth.uid == user;
    }
  }
}

5. 完善登录逻辑

补充现有代码中未实现的_sigIn方法:

Future<void> _sigIn() async {
  try {
    await firebaseAuth.signInWithEmailAndPassword(
      email: email.text, 
      password: password.text
    );
    // 登录成功跳转至笔记页面
    Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => NotesPage()));
  } on FirebaseAuthException catch (e) {
    if (e.code == 'user-not-found') {
      print('未找到该用户');
    } else if (e.code == 'wrong-password') {
      print('密码错误');
    }
  } catch (e) {
    print(e);
  }
}

并在登录页面的build方法中添加登录按钮:

// 在registerElevatedButton()后添加
customSizedBox(),
loginElevatedButton(),

内容的提问来源于stack exchange,提问作者batucode

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 12:48:09