الفصل الحادي عشر: الأمان والخصوصية Chapter 11: Security & Bio-Auth
حماية بيانات المستخدمين هي أولويتنا القصوى في MRE CashBook.
بما إن التطبيق بيتعامل مع بيانات مالية حساسة، كان لازم نوفر طبقتين من الحماية:
منع أي حد يفتح التطبيق غير صاحب الموبايل عن طريق البصمة أو الـ PIN.
تأمين قواعد البيانات والنسخ الاحتياطية من التلاعب عن طريق التشفير.
التطبيق مش بيفتح مباشرة لو المستخدم مفعل "قفل التطبيق". بيظهر شاشة حماية بتطلب البصمة الأول.
Future _authenticate() async {
final success = await context.read().authenticate();
if (success) {
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (_) => const MainScreen()),
);
}
}
بنستخدم باقة local_auth اللي بتتعامل مع حساسات الموبايل بشكل آمن.
final bool canAuth = await _auth.canCheckBiometrics ||
await _auth.isDeviceSupported();
final bool didAuthenticate = await _auth.authenticate(
localizedReason: 'authenticate_to_unlock_app'.tr(),
options: const AuthenticationOptions(
stickyAuth: true,
biometricOnly: true,
),
);
خاصية stickyAuth مهمة جداً لراحة المستخدم:
لو المستخدم جالوا اتصال وخرج من التطبيق ورجع في ثواني، التطبيق مش هيطلب البصمة تاني فوراً وهيفضل فاكر الجلسة، وده بيمنع الإزعاج.
النسخ الاحتياطي (Backup) بيحتوي على كل أرقامك. بنستخدم معيار AES-256 لتشفير الداتا.
final key = Key.fromUtf8('32_chars_long_secure_key_!!!!');
final iv = IV.fromLength(16);
final encrypter = Encrypter(AES(key));
final encrypted = encrypter.encrypt(jsonData, iv: iv);
الملف اللي المستخدم بيحفظه مش مجرد نص، هو ملف مشفر تماماً (Encrypted Binary). لو حاولت تفتحه في Notepad هتلاقي رموز غير مفهومة.
مفتاح التشفير: في MRE CashBook بنستخدم مفتاح ثابت مدمج في الكود، وده بيسمح ليك تسترجع بياناتك حتى لو غيرت الموبايل.
الأمان مش كود بس، لازم نعرف النظام إننا هنستخدم الحساسات.
في ملف Info.plist، لازم نضيف الرسالة اللي هتظهر للمستخدم لما نطلب الـ FaceID:
<key>NSFaceIDUsageDescription</key>
<string>نحتاج للوصول للـ FaceID لتأمين بياناتك المالية.</string>
في ملف AndroidManifest.xml، لازم نضيف التصريح:
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
السبب: المستخدم مش مسجل بصمة في إعدادات الموبايل.
الحل: وجه المستخدم لإعدادات النظام يضيف بصمة الأول.
السبب: لو غيرت الـ Key في تحديث جديد، كل النسخ القديمة مش هتفتح.
| Term | Meaning (AR) |
|---|---|
| AES | معيار تشفير كُتلي متقدم بيستخدم في حماية البيانات الحساسة. |
| IV (Initialization Vector) | رقم عشوائي بيستخدم في بداية التشفير عشان يمنع الأنماط المتكررة. |
| Safe Enclave | منطقة في المعالج مخصصة لحفظ البيانات الحساسة زي البصمات. |
التشفير مش بس encrypt، هو إدارة ذكية للمفاتيح. في MRE CashBook بنتبع الاستراتيجية دي:
الـ AES-256 بيطلب مفتاح طوله 32 حرف. إحنا بنستخدم Key.fromUtf8 عشان نتأكد إن المفتاح متوافق مع المعايير العالمية.
في عمليات الـ Backup، بنستخدم IV.fromLength(16) لضمان استقرار عملية التشفير وفك التشفير بين الأجهزة المختلفة.
إيه اللي بيحصل بالظبط لما تدوس "Unlock"؟
LocalAuthentication البدء.Cubit requests `LocalAuthentication` to start.success.OS returns the result, and Cubit updates State to `success`.| Option | Meaning (AR) | Benefit |
|---|---|---|
stickyAuth | استمرار التحقق لو التطبيق نزل في الخلفية. | UX Smoothness |
biometricOnly | إلزام البصمة فقط (بدون الـ PIN). | Strict Security |
useErrorDialogs | إظهار رسائل خطأ النظام تلقائياً. | System Consistency |
pushReplacement التي تحذف شاشة القفل من ذاكرة التنقل.مش دايماً البصمة بتشتغل من أول مرة. إحنا بنهندل الحالات دي في الكود:
try {
final authenticated = await _auth.authenticate(...);
// success logic
} on PlatformException catch (e) {
if (e.code == auth_error.notAvailable) {
// البصمة مش مدعومة أو مش مفعلة
} else if (e.code == auth_error.lockedOut) {
// المستخدم حاول كتير غلط والجهاز قفل
}
}
| Layer | Tool | Protection Against |
|---|---|---|
| Front Gate | AuthGuardScreen | Physical unauthorized access. |
| Data Storage | encrypt (AES-256) | File theft / Data leakage. |
| Memory | get_it (Singletons) | Memory corruption / Inconsistent states. |
| Transport | Firebase Messaging | Tampered notifications. |
في التطبيقات الأكثر تعقيداً، يفضل استخدام flutter_secure_storage لحفظ الـ Secret Key بشكل ديناميكي لكل جهاز، بدل ما يكون Hardcoded.
دايماً نشغل الـ --obfuscate وقت الـ build عشان نصعب عملية الـ Reverse Engineering للتطبيق.
| Feature | Implementation Tool | Security Level |
|---|---|---|
| App Lock | local_auth | High (Biometric) |
| Data Backup | encrypt (AES) | Very High |
| Auth Gate | AuthGuardScreen | Medium (Flow Control) |
بكدة نكون ضمنا إن MRE CashBook مش بس تطبيق مفيد، لكنه حصن حصين لبيانات المستخدمين.