مقدمة: لماذا تعتبر المصادقة "محلية الصنع" خطرًا؟
\n\nتخيل: أنت تكتب تطبيقًا بلغة Kotlin - سواء كان عميل Android أو خادمًا خلفيًا على Ktor/Spring Boot. تقوم بسرعة بإعداد نموذج تسجيل الدخول، وتخزين كلمة المرور في SharedPreferences وتفرح بأن كل شيء يعمل. وبعد أسبوع تتلقى رسالة: "تم اختراق تطبيقك، وتسربت البيانات". مألوف؟ لسوء الحظ، هذا كلاسيكي.
\n\nالمصادقة الآمنة في Kotlin ليست مجرد "التحقق من كلمة المرور". إنها نظام بيئي كامل: التجزئة، الرموز، الحماية من تزوير الطلبات، التخزين الآمن للأسرار. في هذه المقالة، سنناقش كيفية تجنب الأخطاء الشائعة وبناء نظام دخول موثوق. هيا بنا!
\n\n1. تجزئة كلمات المرور: bcrypt وأصدقاؤه
\n\nالقاعدة الأولى للأمان: لا تقم أبدًا بتخزين كلمات المرور في نص عادي. حتى إذا كنت تستخدم HTTPS، فقد يتم اختراق قاعدة البيانات. مهمتك هي تخزين التجزئة فقط.
\n\nلماذا MD5 و SHA شريران؟
\nهذه الخوارزميات سريعة. والتجزئات السريعة هي حلم المخترق: يمكنه تجربة مليارات المجموعات في الثانية. بدلاً منها، استخدم bcrypt أو scrypt أو Argon2. فهي بطيئة عن قصد ومقاومة للهجمات على GPU.
\n\nمثال بلغة Kotlin باستخدام مكتبة jbcrypt:
import org.mindrot.jbcrypt.BCrypt\n\nfun hashPassword(password: String): String {\n val salt = BCrypt.gensalt(12) // عامل التكلفة 12 - الأمثل\n return BCrypt.hashpw(password, salt)\n}\n\nfun checkPassword(password: String, hashed: String): Boolean {\n return BCrypt.checkpw(password, hashed)\n}\n\nهام: يتم إنشاء الملح تلقائيًا ويتم تضمينه في التجزئة. لست بحاجة إلى تخزينه بشكل منفصل.
\n\n2. JWT: مصادقة خفيفة وآمنة
\n\nJSON Web Token (JWT) هو معيار لنقل الادعاءات (claims) بين الأطراف. في Kotlin، يمكنك استخدام مكتبة java-jwt (Auth0) أو jsonwebtoken (jjwt).
توليد JWT في Kotlin
\n\nimport io.jsonwebtoken.Jwts\nimport io.jsonwebtoken.SignatureAlgorithm\nimport io.jsonwebtoken.security.Keys\nimport java.util.Date\n\nfun generateToken(userId: String, secretKey: String): String {\n val key = Keys.hmacShaKeyFor(secretKey.toByteArray())\n return Jwts.builder()\n .setSubject(userId)\n .setIssuedAt(Date())\n .setExpiration(Date(System.currentTimeMillis() + 3600_000)) // ساعة واحدة\n .signWith(key, SignatureAlgorithm.HS256)\n .compact()\n}\n\nالتحقق من الرمز
\n\nfun validateToken(token: String, secretKey: String): String? {\n return try {\n val key = Keys.hmacShaKeyFor(secretKey.toByteArray())\n val claims = Jwts.parserBuilder()\n .setSigningKey(key)\n .build()\n .parseClaimsJws(token)\n .body\n claims.subject // إرجاع userId\n } catch (e: Exception) {\n null // الرمز غير صالح أو منتهي الصلاحية\n }\n}\n\nنصيحة: لا تقم بتخزين المفتاح السري في الكود. استخدم متغيرات البيئة أو Vault.
\n\n3. التخزين الآمن للرموز على Android
\n\nإذا كنت تكتب تطبيق جوال بلغة Kotlin، فلا يمكن تخزين رمز الوصول في SharedPreferences - فهو ملف مفتوح يمكن قراءته بواسطة تطبيقات أخرى أو مخترق لديه صلاحيات الجذر.
\n\nاستخدم EncryptedSharedPreferences (من AndroidX Security) أو Keystore:
\n\nimport androidx.security.crypto.EncryptedSharedPreferences\nimport androidx.security.crypto.MasterKey\n\nfun saveToken(context: Context, token: String) {\n val masterKey = MasterKey.Builder(context)\n .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)\n .build()\n\n val sharedPreferences = EncryptedSharedPreferences.create(\n context,\n "secure_prefs",\n masterKey,\n