المصادقة الآمنة في Rust: كتابة خلفية محمية

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

لماذا Rust هو الخيار الأمثل للمصادقة؟

\n\n

إذا كنت تكتب تطبيق ويب باستخدام Rust، فأنت بالفعل متقدم خطوة واحدة في مجال الأمان. Rust لا يتسامح مع أخطاء الذاكرة، مما يعني أن العديد من نقاط الضعف (تجاوز سعة المخزن المؤقت، use-after-free) يتم استبعادها في مرحلة التجميع. لكن المترجم لن يحميك من منطق المصادقة السيئ. هذا هو موضوعنا - كيفية بناء مصادقة آمنة في Rust باستخدام الممارسات الحديثة.

\n\n

في هذه المقالة، سنقوم بتجميع وحدة مصادقة كاملة: تجزئة كلمات المرور باستخدام bcrypt، وإصدار رموز JWT، والتحقق عبر middleware في Actix-web، والحماية من الهجمات النموذجية. الكود سيكون عمليًا - يمكنك استخدامه بثقة في مشروعك.

\n\n

1. تجزئة كلمات المرور: لماذا bcrypt وليس SHA-256؟

\n\n

يعتقد العديد من المبتدئين: "سأستخدم SHA-256، إنه سريع وموثوق". وهذا خطأ فادح. SHA هي دالة تجزئة تشفيرية، لكنها سريعة جدًا. يمكن للمهاجم تجربة مليارات التركيبات في الثانية. نحتاج إلى دالة بطيئة، مصممة خصيصًا لكلمات المرور.

\n\n

bcrypt هو المعيار الذهبي. يتضمن "ملح" (salt) و"عامل التكلفة" (cost factor) الذي يمكن زيادته مع تزايد القوة الحاسوبية.

\n\n

إضافة bcrypt إلى Cargo.toml

\n
[dependencies]\nbcrypt = "0.15"
\n\n

تجزئة كلمة المرور

\n
use bcrypt::{hash, verify, DEFAULT_COST};\n\nfn hash_password(plain: &str) -> Result<String, bcrypt::BcryptError> {\n    hash(plain, DEFAULT_COST) // cost = 12 (افتراضيًا)\n}\n\nfn verify_password(plain: &str, hashed: &str) -> bool {\n    verify(plain, hashed).unwrap_or(false)\n}
\n\n

لاحظ: verify يستخرج الملح من التجزئة بنفسه. لست بحاجة لتخزين الملح بشكل منفصل - فهو موجود بالفعل داخل سلسلة التجزئة. هذا آمن ومريح.

\n\n

2. رموز JWT: كيف لا تفشل في المصادقة

\n\n

بعد أن يدخل المستخدم كلمة المرور، يجب أن نصدر له "تصريح مرور". JWT (JSON Web Token) هو تنسيق مضغوط ومكتفي بذاته. لكن الشيطان يكمن في التفاصيل:

\n\n
    \n
  • لا تخزن المفتاح السري في الكود. استخدم متغيرات البيئة.
  • \n
  • حدد عمرًا قصيرًا. رمز الوصول (Access token) - 15-30 دقيقة، رمز التحديث (Refresh token) - 7-30 يومًا.
  • \n
  • لا تضع بيانات حساسة في الحمولة (payload). فقط معرف المستخدم والدور.
  • \n
\n\n

تنفيذ JWT باستخدام jsonwebtoken

\n\n
use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};\nuse serde::{Serialize, Deserialize};\nuse chrono::{Utc, Duration};\n\n#[derive(Debug, Serialize, Deserialize)]\npub struct Claims {\n    pub sub: String,       // معرف المستخدم\n    pub exp: usize,        // طابع زمني لانتهاء الصلاحية\n    pub iat: usize,        // طابع زمني للإصدار\n}\n\npub fn create_token(user_id: &str, secret: &str) -> Result<String, jsonwebtoken::errors::Error> {\n    let now = Utc::now();\n    let claims = Claims {\n        sub: user_id.to_owned(),\n        exp: (now + Duration::minutes(30)).timestamp() as usize,\n        iat: now.timestamp() as usize,\n    };\n    encode(&Header::default(), &claims, &EncodingKey::from_secret(secret.as_bytes()))\n}\n\npub fn validate_token(token: &str, secret: &str) -> Result<Claims, jsonwebtoken::errors::Error> {\n    let token_data = decode::<Claims>(\n        token,\n        &DecodingKey::from_secret(secret.as_bytes()),\n        &Validation::default(),\n    )?;\n    Ok(token_data.claims)\n}
\n\n

3. تجميع كل شيء معًا: Actix-web + middleware

\n\n

الآن سنربط التجزئة و JWT في تطبيق ويب كامل باستخدام Actix-web. سنكتب middleware للتحقق من الرمز في كل طلب محمي.

\n\n

هيكل المشروع

\n
src/\n├── main.rs\n├── auth.rs       # التجزئة، JWT\n├── middleware.rs # التحقق من الرمز\n└── handlers.rs   #                

المدونات

توصيات الكتب