我正试图在我的应用程序中实现与Facebook的登录,这是'工作';但不一定像预期的那样,我会写下我遇到的问题。
-
当我尝试登录时,我没有被重定向到主页,日志显示一个错误这个错误:W/Firestore (27484): (24.1.2) [Firestore]:监听查询(查询目标=(用户电子邮件= = random_email@gmail.com order by名称);limitType=LIMIT_TO_FIRST) failed: Status{code=PERMISSION_DENIED, description=权限缺失或不足。,因为=零}E/flutter (27484): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)]未处理异常:[cloud_firestore/permission-denied]调用者没有执行指定操作的权限。我再次被重定向到登录页面,登录只在第二次尝试中有效。
-
当我退出时,它看起来很好,因为我被重定向到登录页面,但日志显示上面相同的错误。
-
最后一些时候发生的情况是,如果我退出应用程序(按下后退按钮),然后重新打开,我得到重定向到主页,而不是登录页面,它并不总是发生,所以不确定是什么导致的。我将在主页中显示用户数据,在本例中它是空的。
我认为这可能与我在firebase中设置的规则有关,但我不确定,如果有人能指导我或指出我错过或做错了什么,我会非常感激。
我的代码下面:
main.dart
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Wrapper(),
routes: <String, WidgetBuilder>{
'/home': (BuildContext context) => const HomePage(),
'/login': (BuildContext context) => const LoginPage(),
},
);
}
}
wrapper.dart
class Wrapper extends StatelessWidget {
const Wrapper({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
//print(FirebaseAuth.instance.currentUser);
if(FirebaseAuth.instance.currentUser?.email == null){
return const LoginPage();
}
else{
return const HomePage();
}
}
}
login_page.dart
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
String get title => 'login';
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
String userEmail = "";
UserModel? _currentUser;
bool loading = false;
@override
Widget build(BuildContext context) {
return WillPopScope(
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0, vertical: 10.0),
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Email',
),
),
),
const Padding(
padding:
EdgeInsets.symmetric(horizontal: 8.0, vertical: 10.0),
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Password',
),
)),
CustomWidgets.socialButtonRect('Login with Facebook',
facebookColor, FontAwesomeIcons.facebookF, onTap: () async {
await signInWithFacebook();
}),
Padding(
padding: const EdgeInsets.all(15.0),
child:
loading ? const CircularProgressIndicator() : Container(),
),
],
),
), // This trailing comma makes auto-formatting nicer for build methods.
),
onWillPop: () async {
final shouldPop = await showDialog<bool>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Do you want to go exit?'),
actionsAlignment: MainAxisAlignment.spaceBetween,
actions: [
TextButton(
onPressed: () {
Navigator.pop(context, true);
},
child: const Text('Yes'),
),
TextButton(
onPressed: () {
Navigator.pop(context, false);
},
child: const Text('No'),
),
],
);
},
);
return shouldPop!;
},
);
}
Future<void> signInWithFacebook() async {
final LoginResult loginResult =
await FacebookAuth.instance.login(permissions: ['email']);
// Create a credential from the access token
final OAuthCredential facebookAuthCredential =
FacebookAuthProvider.credential(loginResult.accessToken!.token);
final userData = await FacebookAuth.instance.getUserData();
FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
var snapshot = await FirebaseFirestore.instance
.collection('users')
.where('Email', isEqualTo: userData['email'])
.get();
if (snapshot.size == 0) {
await FirebaseFirestore.instance
.collection('users')
.add({'Email': userData["email"], 'Name': userData['name']});
}
//userEmail = userData["email"];
UserModel user = UserModel.fromJson(userData);
_currentUser = user;
setState(() {
loading = true;
});
Navigator.pushNamed(context, '/home');
}
}
home_page.dart
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final FirebaseAuth auth = FirebaseAuth.instance;
bool loading = false;
String name = "";
@override
Widget build(BuildContext context) {
getName();
return Scaffold(
backgroundColor: Colors.blue,
bottomNavigationBar: const BottomBar(),
body: SafeArea(
child: Column(
children: [
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: 2,
itemBuilder: (context, index) {
return matchTile();
}),
Center(
child: ElevatedButton(
onPressed: () async {
//Navigator.pop(context,true);
//Navigator.popUntil(context, ModalRoute.withName('/login'));
Navigator.of(context).pushReplacementNamed('/login');
await signOut();
},
child: Text(name),
style: TextButton.styleFrom(
primary: Colors.redAccent,
onSurface: Colors.red,
),
),
),
],
),
),
);
}
Future<void> signOut() async {
await FacebookAuth.i.logOut();
await FirebaseAuth.instance.signOut();
}
Future<void> getName() async {
User? user = auth.currentUser;
await user?.reload();
user = auth.currentUser;
String? temp = user?.email;
var snapshot = await FirebaseFirestore.instance
.collection('users')
.where('Email', isEqualTo: temp)
.limit(1)
.get()
.then((value) => value.docs[0]);
Map<String, dynamic> data = snapshot.data();
//print('the lenght : $data.length');
setState(() {
name = data['Name'];
});
}
}
最后这些是我在firebase
中设置的规则rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
您可能缺少一个await
。
如果没有这个await
,用户在访问Firestore时不会被记录,因为代码只是运行。
await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);