Flutter Firebase登录异常问题:错误凭证仍可进入主页的排查求助
Hey there, let's figure out why users with wrong credentials are still getting into your app's homepage and fix this issue properly. Looking at your code, there are a few key mistakes causing this behavior—let's break them down and walk through the fixes:
Key Issues in Your Current Code
- Premature SharedPreferences Update: In your login button's
onPressedhandler, you're writing a hardcoded email to SharedPreferences before verifying if the Firebase login was successful. This means even if the user enters wrong credentials, the email is still stored, so the next app launch will direct them to the homepage. - Incorrect Loading State UI: When
loadingis true, you're immediately showing theHomepage()instead of a loading indicator. This skips waiting for Firebase's login result, so users get sent to the homepage before we know if their credentials are valid. - Weak Initial Route Check: Your
runApplogic only checks if there's an email in SharedPreferences, but this doesn't verify if the user is actually authenticated with Firebase. The stored email could be outdated or incorrect.
Step-by-Step Fixes
1. Fix the Login Button Logic
Move the SharedPreferences update to after confirming Firebase login was successful, and remove the hardcoded email. Also, only navigate to the homepage when the login succeeds:
onPressed: () async { if (_formKey.currentState.validate()) { setState(() => loading = true); dynamic result = await authentication.signInWithEmailAndPassword(email, password); print('result at login page $result'); if (result != null) { // Only save email if login succeeds SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.setString('email', email); // Navigate to homepage Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => Homepage())); } else { setState(() { error = 'Sorry, these credentials don\'t work'; loading = false; }); } } },
2. Correct the Loading State UI
Replace the direct Homepage() in the loading state with a proper loading indicator—this keeps the user on the login page until we have a definitive login result:
return loading ? Center(child: CircularProgressIndicator(color: Colors.blue)) : Scaffold( // ... rest of your Scaffold code );
3. Strengthen Initial Route Validation
Instead of relying solely on SharedPreferences, check Firebase's current authentication state on app launch. This ensures we only send users to the homepage if they're actually logged in:
Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); // Don't forget to initialize Firebase! SharedPreferences prefs = await SharedPreferences.getInstance(); var email = prefs.getString('email'); User? firebaseUser = FirebaseAuth.instance.currentUser; runApp(MaterialApp( home: (firebaseUser != null && email != null) ? Homepage() : LoginPage(), )); }
4. Add Error Display in Login Page
Make sure the error message is actually shown to the user so they know why login failed. Add this somewhere in your LoginPage's Scaffold body:
if (error.isNotEmpty) Text( error, style: TextStyle(color: Colors.red, fontSize: 14), ),
Additional Recommendations
- Use Firebase Auth State Listener: For a more robust authentication flow, consider using
FirebaseAuth.instance.authStateChanges()to listen for login/logout events in real-time. This can automatically redirect users if their auth state changes (e.g., token expires). - Avoid Storing Sensitive Data: Storing just the email in SharedPreferences is okay, but never store passwords or auth tokens there. Firebase handles session management automatically, so you don't need to store tokens manually.
- Validate SharedPreferences Data: When checking the stored email, cross-verify it with
firebaseUser?.emailto ensure the stored email matches the currently authenticated user.
内容的提问来源于stack exchange,提问作者stakden1

