المصادقة والتفويض في Rust: من JWT إلى الجلسات
في عالم البرمجة النظامية وبرمجة الويب، اكتسبت Rust سمعة كونها لغة آمنة وسريعة. ومع ذلك، عند إنشاء تطبيقات الويب، غالبًا ما يواجه المطورون مهمة تنفيذ المصادقة (التحقق من هوية المستخدم) والتفويض (التحقق من صلاحيات الوصول). في هذه المقالة، سنستعرض المكتبات والمناهج الرئيسية لتنفيذ هذه الآليات في Rust، بالإضافة إلى تقديم أمثلة عملية للكود.
المفاهيم الأساسية للمصادقة والتفويض
قبل الانتقال إلى الأدوات، من المهم التمييز بين المفاهيم:
- المصادقة — عملية التحقق من أن المستخدم هو من يدّعي هويته. عادةً ما تتم باستخدام اسم المستخدم/كلمة المرور أو الرموز المميزة أو القياسات الحيوية.
- التفويض — تحديد الموارد والإجراءات المتاحة للمستخدم المُصادَق عليه. غالبًا ما يتم تنفيذه من خلال الأدوار (مسؤول، مشرف، مستخدم) أو صلاحيات الوصول.
في Rust، يمكن تنفيذ كلتا العمليتين على المستوى المنخفض (إدارة الرموز المميزة يدويًا) أو باستخدام مكتبات جاهزة.
المكتبات الشائعة للمصادقة في Rust
للعمل مع الجلسات والرموز المميزة في Rust، توجد عدة حلول ناضجة:
actix-identity— لإدارة الجلسات في إطار الويب Actix-web. يدعم جلسات الكوكيز و Redis.jsonwebtoken— مكتبة للعمل مع JWT (رموز JSON للويب). تسمح بإنشاء وتوقيع والتحقق من الرموز المميزة.argon2— تنفيذ خوارزمية تجزئة كلمات المرور Argon2، الموصى بها من قبل OWASP.bcrypt— مكتبة كلاسيكية لتجزئة كلمات المرور.
أدناه سنستعرض كل أداة مع مثال.
مثال 1: المصادقة باستخدام JWT و jsonwebtoken
JWT هي واحدة من أكثر طرق المصادقة شيوعًا في REST API. يحتوي الرمز المميز على ادعاءات (claims) ويتم توقيعه بمفتاح سري. دعونا نلقي نظرة على التنفيذ الأساسي باستخدام مكتبة jsonwebtoken.
// cargo add jsonwebtoken serdeuse jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]struct Claims { sub: String, // معرف المستخدم exp: usize, // وقت الانتهاء (طابع زمني UNIX) role: String, // دور المستخدم}
fn create_token(user_id: &str, role: &str) -> Result<String, jsonwebtoken::errors::Error> { let claims = Claims { sub: user_id.to_owned(), exp: (chrono::Utc::now() + chrono::Duration::hours(24)).timestamp() as usize, role: role.to_owned(), }; encode( &Header::default(), &claims, &EncodingKey::from_secret(b"مفتاحك_السري") )}
fn verify_token(token: &str) -> Result<Claims, jsonwebtoken::errors::Error> { let token_data = decode::<Claims>( token, &DecodingKey::from_secret(b"مفتاحك_السري"), &Validation::default() )?; Ok(token_data.claims)}في هذا المثال، نقوم بإنشاء رمز مميز لمدة 24 ساعة يحتوي على معرف المستخدم ودوره. تتحقق الدالة verify_token من التوقيع وتعيد الادعاءات التي يمكن استخدامها للتفويض.
مثال 2: تجزئة كلمات المرور باستخدام Argon2
لا تقم أبدًا بتخزين كلمات المرور كنص عادي! استخدم Argon2 — خوارزمية تجزئة حديثة وآمنة.
// cargo add argon2use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier};use argon2::password_hash::{SaltString, rand_core::OsRng};
fn hash_password(password: &str) -> String { let salt = SaltString::generate(&mut OsRng); let argon2 = Argon2::default(); argon2.hash_password(password.as_bytes(), &salt) .expect("خطأ في التجزئة")