จากเนื้อหาตอนที่แล้ว ที่เราได้ทำความรู้จักกับกับแนวทางการ
ป้องกันหรือการล็อกแอปด้วยรูปแบบ PIN ที่เราสร้างขึ้นมาเอง
เพื่อให้เห็นแนวทางการทำงาน เกี่ยวกับรูปแบบการยืนยันหรือการ
พิสูจน์ยืนยันตัวตนของผู้ใช้งาน เนื้อหาต่อไปนี้ เราจะมาดูกันต่อโดย
จะเป็นการใช้งานปลั้กอินที่ชื่อว่า local auth ที่อาศัยความสามารถหรือ
คุณสมบัติของเครื่องนั้นๆ ถ้ามีมาใช้ในการตรวจสอบยืนยันตัวตน เพื่อเข้า
ใช้งานหรือจัดการในส่วนที่เรากำหนดได้ ซึ่งรองรับทั้ง การตรวจสอบลายนิ้วมือ,
Touch ID, Face ID, (passcode) รหัสผ่าน, (pin) พิน หรือ (Pattern) รูปแบบ
ทบทวนตอนที่แล้วได้ที่บทความ
สรัางระบบล็อก App ด้วย PIN number ใน Flutter อย่างง่าย http://niik.in/1115
อย่างไรก็ดี ความสามารถนี้ จะเป็นแค่ตัวเลือกเท่านั้น เพราะเราไม่สามารถใช้งานได้กับทุก
อุปกรณ์ และจะใช้งานได้ผู้ใช้ต้องมีการกำหนดหรือตั้งค่าไว้เท่านั้น หากแอปของเราจำเป็นจะต้องมี
การตรวจสอบยืนยัน ก็ควรจะต้องมีรูปแบบเบื้องต้นที่รองรับทุกๆ อุปกรณ์ก่อน เช่น มีระบบสมาชิก
ต้องล็อคอิน หรือระบบ pin ที่กำหนดเองจากตัวอย่างตอนที่แล้ว แบบนี้เป็นต้น
ติดตั้ง local_auth เพื่อใช้งานการพิสูจน์ยืนยันตัวตน
ก่อนที่เราจะใช้งาน การพิสูจน์ยืนยันตัวด้วย local authentication มีสิ่งที่ต้องต้องค่าต่างๆ
ถึงจะใช้งานได้ สามารถดูเพิ่มเติมที่ลิ้งค์ของตัวปลั้กอิน ในที่นี้จะแนะนำสำหรับ android สิ่งแรกเรา
ต้องติดตั้งตัว local_auth ในไฟล์ pubspec.yaml ดังนี้
local_auth: ^2.3.0
จากนั้นในไฟล์ android > app > src > main > AndroidManifest.xml
ให้เพิ่มส่วนนี้ USE_BIOMETRIC เข้าไป
1 2 3 4 5 6 | < uses-permission android:name = "android.permission.INTERNET" /> < uses-permission android:name = "android.permission.USE_BIOMETRIC" /> < application .... .... </manifest> |
จากนั้นในไฟล์ android > app > src > main > kotlin > com > example >
demo_app > MainActivity.kt (com.example.demo_app ตรงนี้จะแตกต่างกัน
แล้วของผู้ใช้งาน ให้ดูแค่ในไฟล์ MainActivity.kt )
เดิมจะเป็นรูปแบบดังนี้
package com.example.demo_app
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity()
ให้เราเปลี่ยนเป็น
package com.example.demo_app
import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity: FlutterFragmentActivity() {
}
ตอนนี้เราเตรียมพร้อมสำหรับใช้งาน local_auth เรียบร้อยแล้ว
แนวทางการใช้งาน Local_auth พิสูจน์ยืนยันตัวตน
เนื้อหานี้เราจะต่อยอดจากบทความตอนที่แล้ว เราจะใช้ local_auth ยืนยันตัวตนแทนระบบ
PIN เดิมที่เราได้ทำไว้ หรือเป็นอีกตัวเลือกหนึ่ง เพื่อใช้สำหรับทำการล็อกแอปได้ โดยตัว local_auth
จะรองรับรูปแบบข้อมูลชีวภาพ 4 รายการ ดังนี้คือ
BiometricType.face:
หมายถึงการยืนยันตัวตนด้วยการสแกนใบหน้า (Face Recognition)
ระบบจะใช้การตรวจสอบคุณสมบัติใบหน้าเพื่อล็อกอินหรือยืนยันตัวตน
BiometricType.fingerprint:
หมายถึงการยืนยันตัวตนด้วยการสแกนลายนิ้วมือ (Fingerprint)
ระบบจะใช้การสแกนลายนิ้วมือในการยืนยันตัวตน
BiometricType.weak:
หมายถึงการยืนยันตัวตนด้วยวิธีที่มีระดับความปลอดภัยต่ำ เช่น Face Unlock ที่ใช้แค่การจับ
คู่รูปร่างใบหน้าพื้นฐาน
ระบบนี้อาจจะสามารถหลอกได้ง่าย เช่น การใช้รูปถ่ายแทน
BiometricType.strong:
หมายถึงการยืนยันตัวตนด้วยวิธีที่มีระดับความปลอดภัยสูง เช่น Face ID หรือระบบสแกนลาย
นิ้วมือที่แม่นยำและยากที่จะถูกหลอก
ระบบนี้มีการป้องกันที่แข็งแกร่งกว่าเพื่อป้องกันการปลอมแปลง
โดยที่ BiometricType.face และ BiometricType.fingerprint เป็นการระบุประเภทที่ชัดเจน
ของไบโอเมตริกซ์ ส่วน BiometricType.weak และ BiometricType.strong จะบ่งบอกถึงระดับ
ความปลอดภัยของการยืนยันตัวตนทางไบโอเมตริกซ์แต่ละประเภท
ดังนั้นเมื่อเรามีการใช้งาน หากขึ้นรองรับอย่างใดอย่างหนึ่ง ก็จะสามารถใช้งานปลั้กอินตัวนี้ได้ ในตัวอย่าง
ที่ผู้เขียนบทความนำมาใช้ทดสอบแสดงรายการที่รองรับ จะมี
[BiometricType.weak, BiometricType.strong]
ทั้งนี้เครื่องทดสอบ รองรับ Face Unlock สแกนลายนิ้วมือ และการใช้ pattern
ดูโค้ดตัวอย่างในหน้าตั้งค่า คำอธิบายแสดงในโค้ด
ไฟล์ settings.dart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | import 'dart:async' ; import 'package:flutter/material.dart' ; import 'package:shared_preferences/shared_preferences.dart' ; import 'package:local_auth/local_auth.dart' ; import 'package:flutter/services.dart' ; import 'pincode.dart' ; enum _SupportState { unknown, supported, unsupported, } class Settings extends StatefulWidget { static const routeName = '/settings' ; const Settings({Key? key}) : super (key: key); @override State<StatefulWidget> createState() { return _SettingsState(); } } class _SettingsState extends State<Settings> { late final SharedPreferences prefs; bool _biometricstatus = false ; // สถานะเปิดใช้ biometric // ส่วนจัดการ local auth final LocalAuthentication auth = LocalAuthentication(); // เรียกใช้งาน _SupportState _supportState = _SupportState.unknown; // สถานะการรองรับ bool? _canCheckBiometrics; // ตรวจสอบรองรับยืนยันด้วยข้อมูลชีวภาพได้ไหม List<BiometricType>? _availableBiometrics; // รายการยืนยันตัวตนที่รองรับ bool _isAuthenticating = false ; // เก็บสถานะกำลังยืนยันตัวตน bool _pincodestatus = false ; // สถานะเปิดใช้ pin bool _authorized = false ; // สถานะเข้าใช้งาน String _pincodevalue = '' ; // ค่า pin ในที่นี้ใช้ 4 ตัวเลข bool _isLoadingPrefs = true ; // สถานะการโหลดค่าจาก SharedPreferences @override void initState() { super .initState(); // โหลดค่าจาก SharedPreferences _loadValueFromSharedPreferences(); auth.isDeviceSupported().then((bool isSupported) { setState(() { if (isSupported) { _supportState = _SupportState.supported; } else { _supportState = _SupportState.unsupported; } // ตรวจสอบรองรับ biometric หรือไม่ _checkBiometrics(); print( "debug: ${_supportState}" ); }); }); } // โหลดข้อมูลจาก SharedPreferences Future<void> _loadValueFromSharedPreferences() async { prefs = await SharedPreferences.getInstance(); setState(() { _biometricstatus = prefs.getBool( 'biometricstatus' ) ?? _biometricstatus; _pincodestatus = prefs.getBool( 'pincodestatus' ) ?? _pincodestatus; _authorized = prefs.getBool( 'authorized' ) ?? _authorized; _pincodevalue = prefs.getString( 'pincodevalue' ) ?? _pincodevalue; _isLoadingPrefs = false ; // โหลดค่าเรียบร้อยแล้ว }); } // ตรวจสอบการรองรับการใช้ข้อมูลชีวภาพยืนยันตัวตนหรือไม่ // เช่น การสแกนลาวนิ้วมือที่มีความแม่นยำสูง การใช้ face ID Future<void> _checkBiometrics() async { late bool canCheckBiometrics; try { canCheckBiometrics = await auth.canCheckBiometrics; } on PlatformException catch (e) { canCheckBiometrics = false ; print(e); } if (!mounted) { return ; } setState(() { print( "debug: _canCheckBiometrics ${canCheckBiometrics}" ); _canCheckBiometrics = canCheckBiometrics; }); } // ฟังก์ชั่นแสดงรายการตรวจสอบที่รองรับ Future<void> _getAvailableBiometrics() async { late List<BiometricType> availableBiometrics; try { availableBiometrics = await auth.getAvailableBiometrics(); } on PlatformException catch (e) { availableBiometrics = <BiometricType>[]; print(e); } if (!mounted) { return ; } setState(() { // สำหรับทดสอบแสดงรายการที่รองรับ print( "debug: ${availableBiometrics}" ); _availableBiometrics = availableBiometrics; }); } // ฟังก์ชั่นสำหรับพิสูจน์ยืนยันโดยให้ระบบเลือกวิธีการให้ Future<void> _authenticate() async { bool authenticated = false ; try { setState(() { _isAuthenticating = true ; // _authorized = false; }); authenticated = await auth.authenticate( localizedReason: 'Let OS determine authentication method' , options: const AuthenticationOptions( stickyAuth: true , ), ); setState(() { _isAuthenticating = false ; }); } on PlatformException catch (e) { print(e); setState(() { _isAuthenticating = false ; // _authorized = false; }); return ; } if (!mounted) { return ; } setState(() { // สำหรับยกเลิกการใช้งาน if (_biometricstatus && authenticated){ print( "debug: cancel using authen" ); _authorized = false ; _biometricstatus = false ; prefs.setBool( "authorized" , _authorized); prefs.setBool( "biometricstatus" , _biometricstatus); } else { // สำหรับกำหนดใช้งาน print( "debug: using authen" ); if (authenticated){ _authorized = authenticated ? true : false ; _biometricstatus = authenticated ? true : false ; prefs.setBool( "authorized" , _authorized); prefs.setBool( "biometricstatus" , _biometricstatus); } } }); } // ฟังก์ชั่นสำหรับพิสูจน์ยืนยันโดยเลือกเป็นข้อมูลชีวภาพ Future<void> _authenticateWithBiometrics() async { bool authenticated = false ; try { setState(() { _isAuthenticating = true ; }); authenticated = await auth.authenticate( localizedReason: 'Scan your fingerprint (or face or whatever) to authenticate' , options: const AuthenticationOptions( stickyAuth: true , biometricOnly: true , // ใช้กรณีรองรับ ), ); setState(() { _isAuthenticating = false ; }); } on PlatformException catch (e) { print(e); setState(() { _isAuthenticating = false ; }); return ; } if (!mounted) { return ; } setState(() { // สำหรับยกเลิกการใช้งาน if (_biometricstatus && authenticated){ print( "debug: cancel using authen" ); _authorized = false ; _biometricstatus = false ; prefs.setBool( "authorized" , _authorized); prefs.setBool( "biometricstatus" , _biometricstatus); } else { // สำหรับกำหนดใช้งาน print( "debug: using authen" ); if (authenticated){ _authorized = authenticated ? true : false ; _biometricstatus = authenticated ? true : false ; prefs.setBool( "authorized" , _authorized); prefs.setBool( "biometricstatus" , _biometricstatus); } } }); } // ฟังก์ชั่นสำหรับยกเลิกการตรวจสอบ เช่น ยังไม่สแกนนิ้ว ขอยกเลิกก่อน Future<void> _cancelAuthentication() async { await auth.stopAuthentication(); setState(() => _isAuthenticating = false ); } @override Widget build(BuildContext context) { if (_isLoadingPrefs) { // คืนค่ากรณี กำลังโหลดค่า SharedPreferences ยังไม่เสร็จ return const Center(child: SizedBox.shrink()); } print( "debug: _biometricstatus ${_biometricstatus}" ); print( "debug: _pincodestatus ${_pincodestatus}" ); print( "debug: _authorized ${_authorized}" ); print( "debug: _pincodevalue ${_pincodevalue}" ); return Scaffold( appBar: AppBar( title: Text( 'Settings' ), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ // Text('Settings Screen'), ListTile( title: Text( 'Lock app with PIN number' ), trailing: Checkbox( value: _pincodestatus, onChanged: (bool? value) async { // เมื่อมีการเปลี่ยนแปลงการตั้งค่า // เปิดหน้ากำหนด pin และรอดำเนินการจากหน้านั้น final result = await Navigator.push( context, MaterialPageRoute(builder: (context) => Pincode()), ); // จัดการเงื่อนไขรับค่าที่ส่งกลับมา print( "debug: ${result}" ); if (result == 'cancel' ) { // ถ้าเป็นการยกเลิก setState(() { _authorized = false ; _pincodestatus = false ; _pincodevalue = '' ; }); } else { // ถ้ามีการตั้งค่า result ที่ส่งกลับมาเป็นค่า code if (result != null ) { setState(() { _authorized = true ; _pincodestatus = true ; _pincodevalue = result; }); } } }, ), ), if (_supportState == _SupportState.supported) ListTile( title: Text( 'Lock app with Biometric' ), trailing: Checkbox( value: _biometricstatus, onChanged: (bool? value) async { // ทดสอบเรียกฟังก์ชั่นแสดงรายการที่รองรับ // _getAvailableBiometrics(); // ทดสอบเรียกใช้ฟังก์ชั่นพิสูจน์ข้อมูลชีวภาพ // _checkBiometrics(); // ใช้การตรวจสอบตามระบบเลือกให้ // _authenticate(); // สำหรับใช้แบบ biometrics // _authenticateWithBiometrics(); if (_canCheckBiometrics== true ){ _authenticateWithBiometrics(); } else { _authenticate(); } }, ), ), ], )), ); } } |
ผลลัพธ์ที่ได้

เมื่อกดเปิดการใช้งาน จะขึ้นการตรวจสอบพิสูจน์ยืนยันตัวตน ในที่นี้ขึ้นเป็นแบบสแกนลายนิ้วมือ หาก
เราทำการสแกนผ่านเรียบร้อย สถานะเปิดใช้งานก็จะถูกเลือก และกรณีเราต้องการปิด ก็แค่เพียงกดอีก
ครั้งจะขึ้นให้สแกนยืนยัน หากสแกนเรียบร้อยแล้วก็จะเป็นการปิดใช้งาน จะเห็นว่าวิธีที่สะดวกรวดเร็วกว่า
วิธีแรกที่เราทำโดยการใช้งาน PIN
การนำ Local_auth ไปใช้งานสำหรับล็อกแอป
จริงๆ แล้วเราสามารถประยุกต์การใช้งาน local_auth ได้ในหลายรูปแบบไม่ใช่แค่เพียงนำมาล็อก
แอป เรายังสามารถใช้สำหรับดึงข้อมูลสมาชิกได้ ทั้งนี้ก็ขึ้นกับการนำไปประยุกต์ใช้งานที่ซับซ้อน ในที่
นี่จะใช้รูปแบบง่ายคือใช้สำหรับล็อกแอปแทนรูปแบบในตอนที่แล้ว เราจะทำที่ไฟล์ launcher.dart ดังนี้
ไฟล์ launcher.dart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | import 'dart:async' ; import 'package:flutter/material.dart' ; import 'package:font_awesome_flutter/font_awesome_flutter.dart' ; import 'package:shared_preferences/shared_preferences.dart' ; import 'package:local_auth/local_auth.dart' ; import 'package:flutter/services.dart' ; import 'home.dart' ; import 'contact.dart' ; import 'profile.dart' ; import 'about.dart' ; import 'settings.dart' ; import 'pincode.dart' ; import '../components/sidemenu.dart' ; enum _SupportState { unknown, supported, unsupported, } class Launcher extends StatefulWidget { static const routeName = '/' ; const Launcher({Key? key}) : super (key: key); @override State<StatefulWidget> createState() { return _LauncherState(); } } class _LauncherState extends State<Launcher> with WidgetsBindingObserver { late final SharedPreferences prefs; bool _biometricstatus = false ; // สถานะเปิดใช้ biometric // ส่วนจัดการ local auth final LocalAuthentication auth = LocalAuthentication(); // เรียกใช้งาน _SupportState _supportState = _SupportState.unknown; // สถานะการรองรับ bool? _canCheckBiometrics; // ตรวจสอบรองรับยืนยันด้วยข้อมูลชีวภาพได้ไหม List<BiometricType>? _availableBiometrics; // รายการยืนยันตัวตนที่รองรับ bool _isAuthenticating = false ; // เก็บสถานะกำลังยืนยันตัวตน bool _pincodestatus = false ; // สถานะเปิดใช้ pin bool _authorized = false ; // สถานะเข้าใช้งาน String _pincodevalue = '' ; // ค่า pin ในที่นี้ใช้ 4 ตัวเลข bool _isLoadingPrefs = true ; // สถานะการโหลดค่าจาก SharedPreferences int _selectedIndex = 0; final List<Widget> _pageWidget = <Widget>[ const Home(), const About(), const Profile(), const Contact(), const Settings(), ]; final List<BottomNavigationBarItem> _menuBar = <BottomNavigationBarItem>[ const BottomNavigationBarItem( icon: Icon(FontAwesomeIcons.house), label: 'Home' , ), const BottomNavigationBarItem( icon: Icon(FontAwesomeIcons.circleInfo), label: 'About' , ), const BottomNavigationBarItem( icon: Icon(FontAwesomeIcons.userLarge), label: 'Profile' , ), const BottomNavigationBarItem( icon: Icon(FontAwesomeIcons.addressCard), label: 'Contact' , ), const BottomNavigationBarItem( icon: Icon(FontAwesomeIcons.gear), label: 'Settings' , ), ]; @override void initState() { super .initState(); // โหลดค่าจาก SharedPreferences _loadValueFromSharedPreferences(); // กำหนดการตรวจจับ สถานะ state ของ app WidgetsBinding.instance.addObserver( this ); auth.isDeviceSupported().then((bool isSupported) { setState(() { if (isSupported) { _supportState = _SupportState.supported; } else { _supportState = _SupportState.unsupported; } // ตรวจสอบรองรับ biometric หรือไม่ _checkBiometrics(); print( "debug: ${_supportState}" ); }); }); } // ตรวจสอบการรองรับการใช้ข้อมูลชีวภาพยืนยันตัวตนหรือไม่ // เช่น การสแกนลาวนิ้วมือที่มีความแม่นยำสูง การใช้ face ID Future<void> _checkBiometrics() async { late bool canCheckBiometrics; try { canCheckBiometrics = await auth.canCheckBiometrics; } on PlatformException catch (e) { canCheckBiometrics = false ; print(e); } if (!mounted) { return ; } setState(() { print( "debug: _canCheckBiometrics ${canCheckBiometrics}" ); _canCheckBiometrics = canCheckBiometrics; }); } @override void dispose() { // ล้างค่าตรวจจับ สถานะ state ของ app WidgetsBinding.instance.removeObserver( this ); super .dispose(); } // ส่วนของการทำงานเมื่อ state ของ app มีการเปลี่ยนแปลง // บาง ค่าของ LifecycleState อาจจะไม่ทำงานได้ @override void didChangeAppLifecycleState(AppLifecycleState state) async { print( "debug: AppLifecycleState: $state" ); if (state == AppLifecycleState.paused) { // ล้างค่าการปลดล็อก ถ้ามีการหยุดชั่วคราวของแอป _authorized = false ; await prefs.setBool( 'authorized' , false ); print( "debug: App is in background." ); } else if (state == AppLifecycleState.resumed) { print( "debug: App is in foreground." ); } else if (state == AppLifecycleState.detached) { // ล้างค่าการปลดล็อก ถ้ามีการปิดแอป ส่วนนี้อาจจะไทม่ทำงานได้ // และบางครั้ง เวลาเริ่มแอปใหม่ อาจจะไม่มีการใส่ pin ได้ _authorized = false ; await prefs.setBool( 'authorized' , false ); print( "debug: App is about to be terminated." ); } } // โหลดข้อมูลจาก SharedPreferences Future<void> _loadValueFromSharedPreferences() async { prefs = await SharedPreferences.getInstance(); setState(() { _biometricstatus = prefs.getBool( 'biometricstatus' ) ?? _biometricstatus; _pincodestatus = prefs.getBool( 'pincodestatus' ) ?? _pincodestatus; _authorized = prefs.getBool( 'authorized' ) ?? _authorized; _pincodevalue = prefs.getString( 'pincodevalue' ) ?? _pincodevalue; _isLoadingPrefs = false ; // โหลดค่าเรียบร้อยแล้ว // เงื่่อนไขถ้ามีการเปิดใช้งานการล็อกแอป และยังไม่ปลดล็อก /* if (_pincodestatus && !_authorized) { _authen(); // เรียกใช้งานการตรวจสอบ pin } */ // เงื่่อนไขถ้ามีการเปิดใช้งานการล็อกแอป และยังไม่ปลดล็อกด้วย biometric if (_biometricstatus && !_authorized){ if (_canCheckBiometrics== true ){ _authenticateWithBiometrics(); } else { _authenticate(); } } }); } // ฟังก์ชั่นสำหรับพิสูจน์ยืนยันโดยให้ระบบเลือกวิธีการให้ Future<void> _authenticate() async { bool authenticated = false ; try { setState(() { _isAuthenticating = true ; // _authorized = false; }); authenticated = await auth.authenticate( localizedReason: 'Let OS determine authentication method' , options: const AuthenticationOptions( stickyAuth: true , ), ); setState(() { _isAuthenticating = false ; }); } on PlatformException catch (e) { print(e); setState(() { _isAuthenticating = false ; // _authorized = false; }); return ; } if (!mounted) { return ; } setState(() { // สำหรับกำหนดใช้งาน print( "debug: using authen" ); if (authenticated){ _authorized = authenticated ? true : false ; _biometricstatus = authenticated ? true : false ; prefs.setBool( "authorized" , _authorized); prefs.setBool( "biometricstatus" , _biometricstatus); } else { // บังคับต้องยืนยันตัวตนถึงจะใช้งานได้ if (_canCheckBiometrics== true ){ _authenticateWithBiometrics(); } else { _authenticate(); } } }); } // ฟังก์ชั่นสำหรับพิสูจน์ยืนยันโดยเลือกเป็นข้อมูลชีวภาพ Future<void> _authenticateWithBiometrics() async { bool authenticated = false ; try { setState(() { _isAuthenticating = true ; }); authenticated = await auth.authenticate( localizedReason: 'Scan your fingerprint (or face or whatever) to authenticate' , options: const AuthenticationOptions( stickyAuth: true , biometricOnly: true , // ใช้กรณีรองรับ ), ); setState(() { _isAuthenticating = false ; }); } on PlatformException catch (e) { print(e); setState(() { _isAuthenticating = false ; }); return ; } if (!mounted) { return ; } setState(() { // สำหรับกำหนดใช้งาน print( "debug: using authen" ); if (authenticated){ _authorized = authenticated ? true : false ; _biometricstatus = authenticated ? true : false ; prefs.setBool( "authorized" , _authorized); prefs.setBool( "biometricstatus" , _biometricstatus); } else { // บังคับต้องยืนยันตัวตนถึงจะใช้งานได้ if (_canCheckBiometrics== true ){ _authenticateWithBiometrics(); } else { _authenticate(); } } }); } // ฟังก์ชั่นสำหรับยกเลิกการตรวจสอบ เช่น ยังไม่สแกนนิ้ว ขอยกเลิกก่อน Future<void> _cancelAuthentication() async { await auth.stopAuthentication(); setState(() => _isAuthenticating = false ); } void _onItemTapped(int index) { setState(() { _selectedIndex = index; }); } // การตรวจสอบ pin โดยแทนที่หน้าหลักด้วยหน้า pincode void _authen() async { String? args = 'pin' ; // ส่งค่านี้ไป เพื่อใช้แยกว่าเป็นการ ตรวจสอบเข้าใช้งาน await Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => Pincode(), settings: RouteSettings(arguments: args // ส่งค่าไปใน arguments ), ), ); } @override Widget build(BuildContext context) { if (_isLoadingPrefs) { // คืนค่ากรณี กำลังโหลดค่า SharedPreferences ยังไม่เสร็จ return const Center(child: SizedBox.shrink()); } print( "debug: _pincodestatus ${_pincodestatus}" ); print( "debug: _authorized ${_authorized}" ); print( "debug: _pincodevalue ${_pincodevalue}" ); return Scaffold( body: _pageWidget.elementAt(_selectedIndex), bottomNavigationBar: BottomNavigationBar( items: _menuBar, currentIndex: _selectedIndex, selectedItemColor: Theme.of(context).primaryColor, unselectedItemColor: Colors.grey, onTap: _onItemTapped, ), drawer: SideMenu(), ); } } |
ผลลัพธ์ที่ได้

เมื่อมีการเปิดการใช้งานการล็อกแอปด้วยข้อมูลชีวภาพ ไม่ว่าจะเป็นการสแกนลายนิ้วมือ หรือการใช้งาน
face ID, Touch ID หรือ Pattern หลังจากเราปิดแอป และกลับมาเปิดใช้งานทุกครั้ง จะขึ้นให้เรา
ยืนยันตัวตนหรือสแกนเพื่อใช้งานก่อนเสมอ ไม่เช่นนั้นก็จะค้างหน้าสแกนจนกว่าจะยืนยันตัวตนผ่าน
และ สมมติเราไม่ต้องการใช้งานแล้ว ก็สามารถเข้าไปใช้งาน และไปปิดการใช้งานเมื่อต้องการได้
เราสามารถนำไปประยุกต์กับระบบสมาชิกได้ เช่น กรณีเป็นระบบสมาชิกที่ต้องทำการล็อคอินเข้าใช้งาน
เราสามารถเก็บข้อมูล key และ api ที่ใช้สำหรับดึงข้อมูลไว้ จะเปิดใช้งานเมื่อยืนยันตัวตนผ่าน ก็สามารถ
นำไปประยุกต์ใช้งานได้
หวังว่าเนื้อหาเกี่ยวกับ Local authentication หรือการตรวจพิสูจน์ยืนยันตัวตนผ่านปลั้กอินที่ชื่อว่า
local_auth จะมีประโยชน์นำไปปรับประยุกต์ใช้งานต่อไปได้ ไม่มากก็น้อย เนื้อหาตอนหน้าจะเป็น
อะไรรอติดตาม