ประยุกต์ระบบ Register Login ด้วย Firebase Auth ใน Flutter
เขียนเมื่อ 2 ปีก่อน โดย Ninenik Narkdeeregister login firebase flutter firebase auth
คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ register login firebase flutter firebase auth
ไปที่
Copy






กรณีเราไม่ต้องการให้มีจำนวนของ user มากเกินไป อาจจะปิดส่วนของ
ต่อเนื่องจากบทความตอนที่แล้ว ที่เราได้เตรียมพร้อมและ
ตั้งค่าส่วนต่างๆ สำหรับใช้งาน Firebase Authentication
โดยเราจะนำมาปรับใช้งานกับรูปแบบระบบสมาชิกที่เคยแนะนำ
ไปแล้ว ดังนั้นวิธีการทำงานก็แทบจะเหมือนเดิม เปลี่ยนแค่
เพียงตัว provider หรือตัวจัดการ จากเดิมที่เราใช้เป็นการส่ง
ข้อมูลไปยัง server ของเราเอง ก็เปลี่ยนมาใช้เป็นใช้งานระบบ
Firebase ถึงแม้การตั้งค่าในตอนที่แล้วอาจจะยุ่งยากหลายขั้นตอน
แต่วิธีการนำมาใช้ก็ง่ายและสะดวก ทบทวนตอนที่แล้วได้ที่บทความ
ใช้งาน Firebase Authentication จัดการระบบสมาชิกใน Flutter http://niik.in/1061
https://www.ninenik.com/content.php?arti_id=1061 via @ninenik
เนื่องจากระบบ Firebase Authentication เราจะจัดการข้อมูลสมาชิกเบื่องต้น สามารถใช้งาน
ได้ทันที ดังนั้นจึงไม่จำเป็นต้องสร้าง Data User model เอง แต่ตัว Firebase สร้างมาให้แล้ว
แต่เราสามารถนำมาปรับเพิ่มเติมได้ ถ้าต้องการ ในที่นี้จะไม่ใช้ Data model เพิ่มเติม
ตัวอย่างโครงสร้าง User Data model ของ Firebase
User( displayName: null, email: example@gmail.com, emailVerified: false, isAnonymous: false, metadata: UserMetadata( creationTime: 2021-11-25 10:30:43.396, lastSignInTime: 2021-11-25 10:34:33.124 ), phoneNumber: null, photoURL: null, providerData, [UserInfo( displayName: null, email: example@gmail.com, phoneNumber: null, photoURL: null, providerId: password, uid: example@gmail.com) ], refreshToken: , tenantId: null, uid: 6TWDv0kfdsfdfdfdf4S2 )
เริ่มต้นใช้งาน Firebase Authentication
ในหน้าหรือไฟล์ที่เราจะใช้งาน Firebase Authentication เราต้องทำการ import class สองค่า
นี้เข้ามาใช้งาน
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_auth/firebase_auth.dart';
และต้องทำการ initialize FlutterFire หรือการกำหนดให้ Flutter กับ Firebase ทำงานร่วมกันได้
เมื่อโหลดหน้านั้นๆ ก่อนเสมอ ด้วยคำสั่ง
try { await Firebase.initializeApp(); } catch(e) { print("Error no initializeApp"); }
สร้าง Provider สำหรับจัดการข้อมูลกับ Firebase Authentication
เป็นการรวมคำสั่งการใช้งาน Firebase Authentication ใน app ของเรา ให้เราสร้างไฟล์ ดังนี้
utils > auth_provider.dart
ไฟล์ auth_provider.dart
import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:shared_preferences/shared_preferences.dart'; // สร้างข้อมูล app state ชื่อ Counter ใช้งานร่วมกับ ChangeNotifier class AuthProvider with ChangeNotifier { final Future<SharedPreferences> _prefs = SharedPreferences.getInstance(); final FirebaseAuth _auth = FirebaseAuth.instance; FirebaseAuth get auth => _auth; // ฟังก์ชั่นดึงสถานะการล็อกอิน จากข้อมูล SharedPreferences Future<bool> getLoginStatus() async { final SharedPreferences prefs = await _prefs; return prefs.getBool('loginSuccess') ?? false; } // ฟังก์ชั่นกำหนดสถานะการล็อกอิน ไว้ใน SharedPreferences Future<bool> setLoginStatus(status) async { final SharedPreferences prefs = await _prefs; return await prefs.setBool('loginSuccess', status); } // ส่วนของการล็อกเอาท์ Future<bool> logout() async { final SharedPreferences prefs = await _prefs; await FirebaseAuth.instance.signOut(); return await prefs.clear(); } // ส่วนของการล็อกอินผ่าน firebase Future<Map<String, dynamic>> authen(String email, String password) async { final SharedPreferences prefs = await _prefs; var result; try { UserCredential userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword( email: email, password: password ); await prefs.setBool("loginSuccess", true); result = json.decode('{"success": "Login successful"}'); } on FirebaseAuthException catch (e) { String err = ''; if (e.code == 'user-not-found') { err = '{"error": "No user found for that email."}'; result = json.decode(err); } else if (e.code == 'wrong-password') { err = '{"error": "Wrong password provided for that user."}'; result = json.decode(err); } else { err = '{"error": "${e.message}"}'; result = json.decode(err); } } return result; } // ส่วนของการสมัครสมาชิกผ่าน firebase Future<Map<String, dynamic>> create(String email, String password) async { var result; try { UserCredential userCredential = await FirebaseAuth.instance.createUserWithEmailAndPassword( email: email, password: password ); result = json.decode('{"success": "Create new user successful"}'); } on FirebaseAuthException catch (e) { String err = ''; if (e.code == 'weak-password') { err = '{"error": "The password provided is too weak."}'; result = json.decode(err); } else if (e.code == 'email-already-in-use') { err = '{"error": "The account already exists for that email."}'; result = json.decode(err); } else if(e.code == 'unknown'){ err = '{"error": "Email and Password are required."}'; result = json.decode(err); } else if(e.code == 'invalid-email'){ err = '{"error": "The email address is badly formatted."}'; result = json.decode(err); }else{ /* print(e.code); print(e.message); */ err = '{"error": "$e"}'; result = json.decode(err); } } catch (e) { String err = '{"error": "$e"}'; result = json.decode(err); } return result; } }
เนื่องจากในไฟล์นี้ จะรวมคำสั่งสำหรับระบบสมาชิก ที่ใช้งานร่วมกับ firebase auth ดังนั้นในนี้เราจึง
ไม่มีการกำหนด initialize FlutterFire เพราะยังไม่ใช่งานในนี้
ใน provider เรากำหนดคำสั่งการทำงานเบื้องต้น คือมีสร้างบัญชีใหม่ ล็อกอิน ล็อกเอาท์ และดึงข้อมูล
สถานะการล็อกอินที่เก็บใน SharedPreferences ไปใช้งาน หากต้องการเพิ่มคำสั่งอื่นๆ ทีหลังก็สามารถ
ปรับเพิ่มได้ตามต้องการ
คำสั่ง createUserWithEmailAndPassword() ของ firebase auth จะทำงานในลักษณะสองขั้นตอนคือ
ทำการสมัครสมาชิก ถ้าสำเร็จก็ล็อกอินอัตโนมัติทันที ล็อกอินในที่นี้คือล็อกอินใน server firebase ดังนั้นสถานะ
ของสมาชิกบน server จึงหมายถึงล็อกอินแล้ว แต่สถานะที่ app ของเรา เรายังไม่กำหนดค่าให้ล็อกอิน
เมื่อสมัครสมาชิกแล้ว ก็จะแจ้งว่าสมัครสำเร็จ แล้วก็ลิ้งค์มายังหน้าล็อกอินให้ผู้ใช้ทำการล็อกอินอีกที นี่คือที่เราจะทำ
อย่างไรก็ตามถ้าต้องการประยุกต์ เมื่อล็อกอินแล้วก็ให้ไปยังหน้า profile เลยก็สามารถทำได้ โดยการใช้การ
ตรวจสอบสถานะการล็อกอิน จากนั้นกำหนดการทำงานเข้าไป เช่น ในหน้า login หรือหน้า register แล้วแต่การ
ปรับประยุกต์ใช้งาน
auth .authStateChanges() .listen((User? user) { if (user == null) { print('User is currently signed out!'); } else { print('User is signed in!'); } });
ในไฟล์ auth_provider.dart รูปแบบคำสั่งก็ไม่มีอะไรซับซ้อน ใช้งานง่าย คำสั่ง create() สำหรับสมัคร
สมาชิกใหม่ คำสั่ง authen() สำหรับล็อกอิน คำสั่ง logout() สำหรับออกจากระบบ จะเห็นว่า เราไม่มีการใช้งาน
User Data model เพราะเราจะใช้งานของ Firebase Auth ที่มีให้มาอยู่แล้ว ซึ่งรองรับข้อมูลที่จำเป็นตามโครง
สร้างข้อมูลด้านบนที่เราแสดงไป ไม่ว่าจะเป็นชื่อที่แสดง วันที่สร้าง วันที่ล็อกอินล่าสุด เบอร์โทร รูปภาพ เป็นต้น
ซึ่งถ้าจะกำหนดใช้งานก็ไปปรับแต่งเพิ่มเติมตามต้องการได้
กำหนดใช้งาน Provider ใน app
ในไฟล์ main.dart จะของยกมาบางส่วนของโค้ด เฉพาะส่วนของการใช้งาน provider
ไฟล์ main.dart บางส่วน
...... .... return MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => AuthProvider()), ], child: MaterialApp( theme: ThemeData( .... ...
ทำการ import AuthProvider เข้าไปใช้งานในไฟล์ main.dart
import 'utils/auth_provider.dart';
การเรียกใช้งาน Provider
สุดท้ายเป็นการเรียกใช้งาน provider ในไฟล์ต่างๆ ตามลำดับ คำอธิบายแสดงในโค้ด
ไฟล์ profile.dart
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_auth/firebase_auth.dart'; import '../utils/auth_provider.dart'; import 'login.dart'; class Profile extends StatefulWidget { static const routeName = '/profile'; const Profile({Key? key}) : super(key: key); @override State<StatefulWidget> createState() { return _ProfileState(); } } class _ProfileState extends State<Profile> { late FirebaseAuth auth; // สำหรับ authen late AuthProvider authProvider; // สำหรับ provider bool _loginSuccess = false; // กำหดตัวแปรสถานะการล็อกอิน // ส่วนของตัวแปรข้อมูลพื้นฐาน String? _id = ''; // ใน firebase ข้อมูลบ uid เป็น string String? _email = ''; @override void initState() { super.initState(); loadSettings(); // เรียกใช้งานตั้งค่าเมื่อเริ่มต้นเป็นฟังก์ชั่น ให้รองรับ async } // ตั้งค่าเริ่มต้น void loadSettings() async { try { await Firebase.initializeApp(); // เชื่อมต่อ firebase กับ app authProvider = context.read<AuthProvider>(); // ใช้งาน provider auth = authProvider.auth; // กำหนด authen _loginSuccess = await authProvider.getLoginStatus(); // ถึงสถานะการล็อกอิน ถ้ามี setState(() { _loginSuccess = _loginSuccess; }); } catch(e) { print("Error no initializeApp"); _loginSuccess = false; } } // ฟังก์ชั่นสำหรับดึงข้อมูลผู้ใช้ Future<bool> fetchUser() async { await Firebase.initializeApp(); // เชื่อมต่อ firebase กับ app // ใช้งาน provider authProvider = context.read<AuthProvider>(); _loginSuccess = await authProvider.getLoginStatus(); // ถึงสถานะการล็อกอิน ถ้ามี var currentUser = auth.currentUser; // อ้างอิงผู้ใช้ปัจจุบัน if (currentUser != null) { // ถ้ามีข้อมูล _id = currentUser.uid; // เอาค่ามาเก็บในัวแร เพื่อใช้แสดง _email = currentUser.email; print(currentUser); // แสดงรายละเอียดข้อมูลของผู้ใช้ทั้งหมดว่ามีอะไรบ้าง } return true; } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Profile'), ), body: FutureBuilder<bool>( future: fetchUser(), // ข้อมูล Future builder: (context, snapshot) { if (snapshot.hasData) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('Profile Screen'), Visibility( // ส่วนที่แสดงกรณีล็อกอินแล้ว visible: _loginSuccess, // ใช้สถานะการล็อกอินกำหนดกรแสดง child: Column( children: [ FlutterLogo(size: 100,), Text('Welcome member'), Text(_email!), // แสดงอีเมล ElevatedButton( onPressed: () async { // เมื่อล็อกเอาท์ // ทำการออกจากระบบ await authProvider.logout(); setState(() { _loginSuccess = false; }); }, child: Text('Logout'), ), ], ), ), Visibility( // ส่วนที่แสดงกรณียังไม่ได้ล็อกอิน visible: !_loginSuccess, // ใช้สถานะตรงข้ามการล็อกอินกำหนดกรแสดง child: ElevatedButton( onPressed: () async { // กำหดให้รอค่า หลังจากเปิดไปหน้า lgoin final result = await Navigator.push( context, MaterialPageRoute(builder: (context) => Login(), settings: RouteSettings( arguments: null ), ), ); // ถ้ามีการปิดหน้าที่เปิด และส่งค่ากลับมาเป็น true if (result == true) { await fetchUser(); setState(() { _loginSuccess = true; }); } }, child: Text('Go to Login'), ), ), ], ) ); } else if (snapshot.hasError) { // ถ้ามี error return Text('${snapshot.error}'); } return const CircularProgressIndicator(); }, ), ); } }
ไฟล์ login.dart
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_auth/firebase_auth.dart'; import '../utils/auth_provider.dart'; import 'register.dart'; class Login extends StatefulWidget { static const routeName = '/login'; const Login({Key? key}) : super(key: key); @override State<StatefulWidget> createState() { return _LoginState(); } } class _LoginState extends State<Login> { late FirebaseAuth auth; late AuthProvider authProvider; // สร้างฟอร์ม key หรือ id ของฟอร์มสำหรับอ้างอิง final _formKey = GlobalKey<FormState>(); // กำหนดตัวแปรรับค่า final _email = TextEditingController(); final _password = TextEditingController(); // กำหนดสถานะการแสดงแบบรหัสผ่าน bool _isHidden = true; bool _authenticatingStatus = false; @override void initState() { super.initState(); loadSettings(); } // ตั้งค่าเริ่มต้น void loadSettings() async { try { await Firebase.initializeApp(); authProvider = context.read<AuthProvider>(); auth = authProvider.auth; auth .authStateChanges() .listen((User? user) { if (user == null) { print('User is currently signed out!'); } else { print('User is signed in!'); authProvider.setLoginStatus(true); Navigator.pop(context, true); // ปิดหน้านี้พร้อมคืนค่า true } }); } catch(e) { print("Error no initializeApp"); } } @override void dispose() { _email.dispose(); // ยกเลิกการใช้งานที่เกี่ยวข้องทั้งหมดถ้ามี _password.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Login'), ), body: SingleChildScrollView( child: Form( key: _formKey, // กำหนด key child: Padding( padding: const EdgeInsets.all(15.0), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ SizedBox(height: 20.0,), FlutterLogo( size: 100, ), Text('Login Screen'), TextFormField( decoration: InputDecoration( hintText: 'Email', icon: Icon(Icons.email_outlined), ), controller: _email, // ผูกกับ TextFormField ที่จะใช้ ), SizedBox(height: 5.0,), TextFormField( decoration: InputDecoration( hintText: 'Password', icon: Icon(Icons.vpn_key), suffixIcon: IconButton( onPressed: (){ setState(() { _isHidden = !_isHidden; // เมื่อกดก็เปลี่ยนค่าตรงกันข้าม }); }, icon: Icon( _isHidden // เงื่อนไขการสลับ icon ? Icons.visibility_off : Icons.visibility ), ), ), controller: _password, // ผูกกับ TextFormField ที่จะใช้ obscureText: _isHidden, // ก่อนซ่อนหรือแสดงข้อความในรูปแบบรหัสผ่าน ), SizedBox(height: 10.0,), Visibility( visible: !_authenticatingStatus, child: ElevatedButton( onPressed: () async { // เปลี่ยนสถานะเป็นกำลังล็อกอิน setState(() { _authenticatingStatus = !_authenticatingStatus; }); // อ้างอิงฟอร์มที่กำลังใช้งาน ตรวจสอบความถูกต้องข้อมูลในฟอร์ม if (_formKey.currentState!.validate()) { //หากผ่าน FocusScope.of(context).unfocus(); // ยกเลิดโฟกัส ให้แป้นพิมพ์ซ่อนไป String email = _email.text; String password = _password.text; // ทำการล็อกอิน firebase โดยใช้งาน provider var result = await authProvider.authen(email, password); // จำลองเปรียบเทียบค่า เพื่อทำการล็อกอิน if(result['success']!=null){ // ล็อกอินผ่าน ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Login Successful')), ); Navigator.pop(context, true); // ปิดหน้านี้พร้อมคืนค่า true }else{ if(result['error']!=null){ // ล็อกอินไม่ผ่านมี error String error = result['error']; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('${error}.. try agin!')), ); setState(() { _authenticatingStatus = !_authenticatingStatus; }); }else{ // ล็อกอินไม่ผ่าน อื่นๆ ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error.. try agin!')), ); setState(() { _authenticatingStatus = !_authenticatingStatus; }); } } } }, child: Container( alignment: Alignment.center, width: double.infinity, child: const Text('Login'), ), ), ), Visibility( visible: _authenticatingStatus, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ CircularProgressIndicator(), SizedBox(width: 10.0,), Text(" Authenticating ... Please wait") ], ), ), SizedBox(height: 30.0,), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Or '), InkWell( child: Text('Register', style: TextStyle( decoration: TextDecoration.underline, color: Colors.blue )), onTap: () async { // เปิดหน้า สมัครสมาชิก โดย แทนที่ route ล็อกอินเดิม Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => Register(), settings: RouteSettings( arguments: null ), ), ); }, ) ], ) ], ) ), ), ), ), ); } }
ไฟล์ register.dart
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_auth/firebase_auth.dart'; import '../utils/auth_provider.dart'; import 'login.dart'; class Register extends StatefulWidget { static const routeName = '/register'; const Register({Key? key}) : super(key: key); @override State<StatefulWidget> createState() { return _RegisterState(); } } class _RegisterState extends State<Register> { late FirebaseAuth auth; late AuthProvider authProvider; // สร้างฟอร์ม key หรือ id ของฟอร์มสำหรับอ้างอิง final _formKey = GlobalKey<FormState>(); // กำหนดตัวแปรรับค่า final _email = TextEditingController(); final _password = TextEditingController(); // กำหนดสถานะการแสดงแบบรหัสผ่าน bool _isHidden = true; bool _registeringStatus = false; @override void initState() { super.initState(); loadSettings(); // เรียกใช้งานตั้งค่าเมื่อเริ่มต้นเป็นฟังก์ชั่น ให้รองรับ async } // ตั้งค่าเริ่มต้น void loadSettings() async { try { await Firebase.initializeApp(); authProvider = context.read<AuthProvider>(); auth = authProvider.auth; } catch(e) { print("Error no initializeApp"); } } @override void dispose() { _email.dispose(); // ยกเลิกการใช้งานที่เกี่ยวข้องทั้งหมดถ้ามี _password.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Register'), ), body: SingleChildScrollView( child: Form( key: _formKey, // กำหนด key child: Padding( padding: const EdgeInsets.all(15.0), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ SizedBox(height: 20.0,), FlutterLogo( size: 100, ), Text('Register Screen'), TextFormField( decoration: InputDecoration( hintText: 'Email', icon: Icon(Icons.email_outlined), ), controller: _email, // ผูกกับ TextFormField ที่จะใช้ ), SizedBox(height: 5.0,), TextFormField( decoration: InputDecoration( hintText: 'Password', icon: Icon(Icons.vpn_key), suffixIcon: IconButton( onPressed: (){ setState(() { _isHidden = !_isHidden; // เมื่อกดก็เปลี่ยนค่าตรงกันข้าม }); }, icon: Icon( _isHidden // เงื่อนไขการสลับ icon ? Icons.visibility_off : Icons.visibility ), ), ), controller: _password, // ผูกกับ TextFormField ที่จะใช้ obscureText: _isHidden, // ก่อนซ่อนหรือแสดงข้อความในรูปแบบรหัสผ่าน ), SizedBox(height: 10.0,), Visibility( visible: !_registeringStatus, child: ElevatedButton( onPressed: () async { // เปลี่ยนสถานะกำลังสมัครสมาชิก setState(() { _registeringStatus = !_registeringStatus; }); if (_formKey.currentState!.validate()) { //หากผ่าน FocusScope.of(context).unfocus(); // ยกเลิดโฟกัส ให้แป้นพิมพ์ซ่อนไป String email = _email.text; String password = _password.text; // เรียกใช้งานการสมัครสมาชิกใหม่ด้วย firebase ผ่าน provider var result = await authProvider.create(email, password); if(result['success']!=null){ // สร้างบัญชีสำเร็จ ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Create new user Successful')), ); Navigator.pushReplacement( // ไปหน้าล็อกอิน context, MaterialPageRoute(builder: (context) => Login(), settings: RouteSettings( arguments: null ), ), ); }else{ if(result['error']!=null){ // สร้างบัญชีไม่ผ่าน String error = result['error']; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('${error}.. try agin!')), ); setState(() { _registeringStatus = !_registeringStatus; }); }else{ // สร้างบัญชีไม่ผ่าน อื่นๆ ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error.. try agin!')), ); setState(() { _registeringStatus = !_registeringStatus; }); } } } }, child: Container( alignment: Alignment.center, width: double.infinity, child: const Text('Register'), ), ), ), Visibility( visible: _registeringStatus, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ CircularProgressIndicator(), SizedBox(width: 10.0,), Text(" Registering ... Please wait") ], ), ), SizedBox(height: 30.0,), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Already member? '), InkWell( child: Text('Login', style: TextStyle( decoration: TextDecoration.underline, color: Colors.blue )), onTap: (){ Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => Login(), settings: RouteSettings( arguments: null ), ), ); }, ) ], ) ], ) ), ), ), ), ); } }
ตัวอย่างลำดับการทำงาน
เราลองสมัครสมาชิกโดยกรอกข้อมูลที่ไม่ถูกต้องดูการทำงาน จะได้ดังรูป

ต่อไปลองกรอกข้อมูลให้ผ่านเงื่อนไข และถูกต้อง ก็จะได้เป็นดังนี้

เมื่อกรอกข้อมูลถูกต้อง และทำการสมัครสมาชิกเรียบร้อย ก็กลับมายังหน้าล็อกอิน
ให้เราทำการล็อกอินเข้าใช้งานใน app อีกที
ตอนนี้บนเว็บไซต์ในหน้า project Firebase ของเราก็จะมี user เพิ่มเข้ามาดังรูป

ต่อไปลองทำการล็อกอินเข้าใช้งาน จะได้เป็นดังนี้

หากยังไม่ได้ล็อกเอาท์ เมื่อปิด app แล้วเปิดขึ้นมาใหม่ ระบบก็จะยังจำสถานะการล็อกอินไว้
เราสามารถดึงข้อมูลต่างๆ มาแสดงในหน้า profile ได้ หากไปประยุกต๋เพิ่มเติม เช่น แสดงชื่อ เบอร์
โทร หรือวันล่าเข้าใช้งานล่าสุด หรือรูปภาพโพรไฟล์ เป็นต้น
ถึงแม้ว่า Firebase Auth จะสะดวก เราก็ควรจะใช้เฉพาะที่จำเป็น หรือให้เหมาะกับ
รูปแบบงานที่จะใช้ เพราะเป็นการใช้ส่วนเสริมจากภายนอก หากมีปัญหาอาจจะกระทบการใช้งานรวม
โดยที่เราอาจจะไม่สามารถควบคุมได้
เนื้อหาเกี่ยวกับ Firebase Auth ก็เป็นแนวทางหนึ่งสำหรับการปรับประยุกต์ใช้งานให็หลากหลาย สามารถ
นำไปต่อยอดเพิ่มเติมได้ หรืออาจจะต้องปรับเปลี่ยนการใช้งานให้เข้ากับ logic การทำงานของระบบของเราด้วย
เพราะการใช้งานในอีกรูปแบบ ก็อาจจะต้องใช้คำสั่งและวิธีที่แตกต่างกันไป
เพิ่มเติมเนื้อหา ครั้งที่ 1 วันที่ 25-11-2021
กรณีต้องการใช้งาน การล็อกอินแบบไม่ระบุตัวตน Anonymous sign-in
สมมติว่าเราต้องการวิเคราะห์ หรือเก็บสถิติ หรือใช้งานร่วมกับ google analytic หรืออื่นๆ
และไม่ต้องการให้ข้อมูลของสมาชิกในส่วนนี้ ต้องการแค่ประสบการณ์การใช้งาน เราสามารถกำหนด
ให้เรียกใช้รูปแบบการล็อกอินแบบไม่ระบุตัวต้น ซึ่งใน firebase authen ก็มีให้เราเปิดใช้งาน
โดยเข้าไปที่ firebase project console ทำการเพิ่ม provider ใหม่ แล้วเลือก Anonymous แล้ว
เปิดใช้งาน


Anonymous จะมี User Data model เหมือนกันผู้ใช้ในระบบ Email,Password เพียงแต่ข้อมูลที่
ต้องระบุตัวตนต่างๆ จะเป็นค่า null และ มี isAnonymous เป็น true สำหรับ Anonymous user ก็จะมี
uid ที่ไม่ซ้ำด้วย ดังนั้นถ้าเราใช้งานร่วมกันกับผู้ใช้ที่สมัครสมาชิกปกติ และเวลาเรียกใช้ข้อมูล เราอาจจะ
ต้องกำหนดค่าข้อมูล เป็นว่าง ในลักษณะนี้แทน
if (currentUser != null) { // ถ้ามีข้อมูล _id = currentUser.uid; // เอาค่ามาเก็บในัวแร เพื่อใช้แสดง _email = currentUser.email ?? ''; print(currentUser); // แสดงรายละเอียดข้อมูลของผู้ใช้ทั้งหมดว่ามีอะไรบ้าง }
จะเห็นส่วนของอีเมล ถ้าเป็น Anonymous user จะมีค่าเป็น null ดังนั้น ถ้าเราไม่กำหนดเงื่อนไขว่า ถ้าเป็น
null ให้เป็น String ค่าว่าง เวลาตัวแปร _email ถูกเรียกใช้ จะเกิด error เป็นค่า null ได้ หรือวิธีแก้ปัญหาอีก
วิธี เราสามารถจำแนกประเภทของผู้ใช้โดยใช้ค่า isAnonymous คือ ถ้าเป็นสมาชิกปกติ ค่านี้จะเป็น false แต่
ถ้าเป็น Anonymous user ค่านี้จะเป็น true
จำไว้ว่า Anonymous user ค่า user ไม่ใช่ค่า null เพียงแต่มีข้อมูลด้านบนบางค่าเป็น null เมื่อจะสร้างส่วน
ของการล็อกอินสำหรับกรณีนี้ สมมติเราใช้เป็น Guest ก็มีเพียงแค่ปุ่มเดียว เพื่อทำคำสั่งก็ได้แล้ว โดยเรียกใช้งาน
คำสั่งดังนี้
UserCredential userCredential = await FirebaseAuth.instance.signInAnonymously();
กรณีใช้งาน AuthProvider ในไฟล์ auth_provider.dart สามารถเพิ่มคำสั่งนี้เข้าไปได้
Future<Map<String, dynamic>> guest() async { final SharedPreferences prefs = await _prefs; var result; try{ UserCredential userCredential = await FirebaseAuth.instance.signInAnonymously(); await prefs.setBool("loginSuccess", true); result = json.decode('{"success": "Login successful"}'); }catch(e){ String err = '{"error": "$e"}'; result = json.decode(err); } return result; }
เวลาเรียกใช้งาน เช่นในหน้า profile ก็อาจจะเพิ่มปุ่ม สำหรับ Guest แล้วไปในลักษณะดังนี้ได้
ElevatedButton( onPressed: () async { var result = await authProvider.guest(); setState(() { _loginSuccess = true; }); }, child: Text('Guest'), ),
กรณีที่เป็น Anonymous user ถ้าออกจากระบบและเข้าใหม่ ระบบจะเพิ่มข้อมูลเข้าไปใน Firebase
ใหม่ทุกครั้ง โดยมีค่า uid ใหม่

กรณีเราไม่ต้องการให้มีจำนวนของ user มากเกินไป อาจจะปิดส่วนของ
การล็อกเอาท์ของ user นี้ออกไปก็ได้ อย่างไรก็ตามขึ้นกับการปรับประยุกต์ใช้งานและความเหมาะสม
กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ

อ่านต่อที่บทความ
-
27 Nov2021การเปลี่ยนชื่อ App ชื่อ Package และไอคอน ใน Flutter อ่าน 6,077
เนื้อหาตอนต่อไปนี้จะมาแนะนำวิธีการเปลี่ยนชื่อ app และ ไอคอนของ app
เนื้อหาที่เกี่ยวข้อง
-
05 Nov2021การใช้งาน Provider จัดการข้อมูล App State ใน Flutter อ่าน 11,341
เนื้อหาตอนต่อไปนี้เราจะมาดูเกี่ยวกับการใช้งาน provider จ้ดการข้อมูล app s
-
06 Nov2021จัดการข้อมูลด้วย SQL Database โดยใช้ Sqflite ใน Flutter อ่าน 10,400
เนื้อหาตอนต่อไปนี้จะมาแนะนำ การบันทึกข้อมูลไว้ใน app ในรูปแบบ SQLite data
-
08 Nov2021การใช้งาน Form และ Form Validation ใน Flutter อ่าน 12,247
เนื้อหาตอนต่อไปนี้ เราจะมาดูเกี่ยวกับการใช้งาน form ใน flutter เริ่มตั้งแ
-
10 Nov2021การจัดการข้อมูลของ Form Element อื่นๆ ใน Flutter อ่าน 3,786
เนื้อหาต่อไปนี้ จะมาดูต่อเกี่ยวกับการใช้งานฟอร์ม ต่อจาก เนื้อหาตอนที่แล้ว
-
11 Nov2021ประยุกต์ใช้งาน Form บันทึกลงฐานข้อมูล ใน Flutter อ่าน 3,848
เนื้อหานี้จะเป็นเนื้อหาประยุกต์เพิ่มเติม เล็กน้อยเกี่ยวกับการ ปรับใช้งานฟ
-
22 Nov2021ประยุกต์เก็บข้อมูลด้วย shared preferences ใน Flutter อ่าน 5,414
เนื้อหาตอนต่อไปนี้ เราจะมาประยุกต์การใช้งาน plugin ที่ใช้ สำหรับเก็บข้อมู
-
24 Nov2021ประยุกต์ระบบ Register Login ผ่าน API บน server ใน Flutter อ่าน 9,352
เนื้อหาต่อไปนี้เป็นการประยุกต์ใช้งาน ต่อเนื้อง จากเนื้อหาตอนที่แล้ว เกี่ย
-
25 Nov2021ใช้งาน Firebase Authentication จัดการระบบสมาชิกใน Flutter อ่าน 2,852
สำหรับเนื้อหานี้จะเป็นแนวทางการประยุกต์อีกรูปแบบ ของระบบสมาชิก ที่เราไม่จ
-
กำลังอ่านเนื้อหานี้อยู่26 Nov2021ประยุกต์ระบบ Register Login ด้วย Firebase Auth ใน Flutter อ่าน 5,977
ต่อเนื่องจากบทความตอนที่แล้ว ที่เราได้เตรียมพร้อมและ ตั้งค่าส่วนต่างๆ สำห
-
27 Nov2021การเปลี่ยนชื่อ App ชื่อ Package และไอคอน ใน Flutter อ่าน 6,077
เนื้อหาตอนต่อไปนี้จะมาแนะนำวิธีการเปลี่ยนชื่อ app และ ไอคอนของ app
URL สำหรับอ้างอิง
Top
Copy
ขอบคุณทุกการสนับสนุน
![]()