Flutter应用Firestore规则request.auth != null无数据返回问题
问题:Firestore设置认证规则后Flutter应用无法读取数据
问题背景
使用Flutter开发应用,配置Firestore安全规则要求用户必须认证(request.auth != null)后,尽管已有两个测试账号完成注册并登录,应用仍无法在ListView中以卡片形式展示Firestore中的数据。Firebase与应用通信正常,用户UID已分配,但数据无法加载。
当前Firestore安全规则
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /Events { allow read, write: if request.auth != null; } } }
Flutter核心代码(HomePage)
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:plancel/components/event_card.dart'; import 'package:plancel/components/menu_drawer.dart'; import 'package:plancel/settings.dart'; class HomePage extends StatelessWidget { HomePage({super.key}); final user = FirebaseAuth.instance.currentUser!; // 退出登录方法 void signUserOut() { FirebaseAuth.instance.signOut(); } @override Widget build(BuildContext context) { // 跳转到设置页 void goToSettingsPage() { Navigator.pop(context); Navigator.push( context, MaterialPageRoute( builder: (context) => const SettingsPage(), )); } return Scaffold( backgroundColor: Colors.grey[300], appBar: AppBar( backgroundColor: Colors.grey[900], title: const Text( 'APP NAME', style: TextStyle( color: Colors.white, fontSize: 30, fontWeight: FontWeight.w300, ), ), centerTitle: true, ), floatingActionButton: FloatingActionButton( onPressed: () { Navigator.pushNamed(context, '/eventform'); }, backgroundColor: Colors.grey[900], child: const Icon(Icons.add), ), drawer: MenuDrawer( onSettingsTap: goToSettingsPage, onSignOut: signUserOut, ), body: StreamBuilder( stream: FirebaseFirestore.instance .collection("Events") .orderBy("date", descending: false) .snapshots(), builder: (context, snapshot) { if (snapshot.hasData) { return ListView.builder( itemCount: snapshot.data!.docs.length, itemBuilder: (context, index) { final post = snapshot.data!.docs[index]; return EventCard( titleEvent: post['eventTitle'], locationEvent: post['eventLocation'], dateEvent: post['date'], timeHour: post['timeHour'], timeMinute: post['timeMinute'], ); }, ); } else if (snapshot.hasError) { return Center( child: Text('错误${snapshot.error}'), ); } return const Center(child: CircularProgressIndicator()); }, ), ); } }
错误提示
错误截图显示权限被拒绝(Permission denied),说明Firestore读取请求未通过规则校验。
解决方案
1. 修正Firestore规则路径匹配
当前规则仅匹配Events集合本身,而读取集合内的文档需要匹配到文档层级。修改规则为:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // 使用通配符匹配集合下所有文档及子集合 match /Events/{document=**} { allow read, write: if request.auth != null; } } }
2. 确保认证状态稳定后再请求数据
原代码中直接获取currentUser!可能存在初始化时用户未完成认证的情况,建议先监听认证状态,确认用户登录后再加载Firestore数据流:
body: StreamBuilder<User?>( stream: FirebaseAuth.instance.authStateChanges(), builder: (context, authSnapshot) { if (authSnapshot.hasData && authSnapshot.data != null) { // 用户已登录,加载Firestore数据 return StreamBuilder<QuerySnapshot>( stream: FirebaseFirestore.instance .collection("Events") .orderBy("date", descending: false) .snapshots(), builder: (context, snapshot) { if (snapshot.hasData) { return ListView.builder( itemCount: snapshot.data!.docs.length, itemBuilder: (context, index) { final post = snapshot.data!.docs[index]; return EventCard( titleEvent: post['eventTitle'], locationEvent: post['eventLocation'], dateEvent: post['date'], timeHour: post['timeHour'], timeMinute: post['timeMinute'], ); }, ); } else if (snapshot.hasError) { return Center(child: Text('错误:${snapshot.error}')); } return const Center(child: CircularProgressIndicator()); }, ); } else { // 用户未登录,显示登录提示或跳转登录页 return const Center(child: Text('请先登录')); } }, ),
3. 验证数据写入权限
如果Firestore中的测试数据是在规则生效前写入的,需确认这些文档的读取权限已被当前规则覆盖,或重新由已认证用户写入数据。
内容的提问来源于stack exchange,提问作者Mutant52
相关产品推荐
相关产品推荐

