التفويض والمصادقة في Swift (iOS/macOS)
التفويض والمصادقة هما مكونان أساسيان لأي تطبيق حديث. في نظام Apple البيئي (iOS/macOS)، يتمتع المطورون بإمكانية الوصول إلى أُطر عمل ومكتبات قوية تُبسّط هذه العمليات. في هذه المقالة، سنستعرض الأساليب الرئيسية، والمكتبات الشائعة، ونقدم أمثلة عملية بلغة Swift.
المفاهيم الأساسية
قبل الانتقال إلى الكود، من المهم التمييز بين المصطلحين:
- المصادقة — التحقق من هوية المستخدم (مثل: اسم المستخدم + كلمة المرور، Face ID، Touch ID).
- التفويض — تحديد صلاحيات الوصول بعد المصادقة (مثل: هل يمكن للمستخدم عرض بيانات معينة).
الإمكانيات المدمجة من Apple
1. LocalAuthentication (Face ID / Touch ID)
يسمح إطار العمل LocalAuthentication باستخدام البيانات البيومترية للجهاز للمصادقة.
import LocalAuthentication
func authenticateWithBiometrics() { let context = LAContext() var error: NSError? // نتحقق من توفر القياسات الحيوية guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else { print("القياسات الحيوية غير متوفرة: \\(error?.localizedDescription ?? "خطأ")") return } // نطلب المصادقة context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "سجّل الدخول للوصول إلى التطبيق") { success, authError in DispatchQueue.main.async { if success { print("تمت المصادقة بنجاح") } else { print("خطأ: \\(authError?.localizedDescription ?? "خطأ غير معروف")") } } }}2. Keychain Services
Keychain هو مخزن آمن لكلمات المرور والرموز المميزة. استخدمه لتخزين بيانات الاعتماد بعد المصادقة.
import Security
func saveToKeychain(service: String, account: String, password: String) { guard let passwordData = password.data(using: .utf8) else { return } let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: account, kSecValueData as String: passwordData ] // نحذف البيانات القديمة إن وجدت SecItemDelete(query as CFDictionary) // نضيف البيانات الجديدة let status = SecItemAdd(query as CFDictionary, nil) if status == errSecSuccess { print("تم حفظ البيانات في Keychain") } else { print("خطأ في الحفظ: \\(status)") }}
func readFromKeychain(service: String, account: String) -> String? { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: account, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne ] var item: CFTypeRef? let status = SecItemCopyMatching(query as CFDictionary, &item) guard status == errSecSuccess, let data = item as? Data else { return nil } return String(data: data, encoding: .utf8)}المكتبات الشائعة للتفويض
1. Firebase Authentication
يوفر Firebase حلاً جاهزاً للمصادقة عبر البريد الإلكتروني/كلمة المرور، Google، Apple، Facebook وغيرها من المزوّدين.
import FirebaseAuth
func signInWithEmail(email: String, password: String) { Auth.auth().signIn(withEmail: email, password: password) { result, error in if let error = error { print("خطأ في تسجيل الدخول: \\(error.localizedDescription)") return } print("المستخدم سجّل الدخول: \\(result?.user.uid ?? "لا يوجد")") }