رموز JWT في PHP: دليل شامل للتنفيذ
\n\nJWT (JSON Web Token) هو معيار مفتوح (RFC 7519) لإنشاء رموز الوصول بناءً على تنسيق JSON. في PHP، يُستخدم JWT على نطاق واسع لتنفيذ المصادقة عديمة الحالة (stateless authentication) في REST API، والتطبيقات ذات الصفحة الواحدة (SPA)، والخدمات المصغرة.
\n\nفي هذه المقالة، سنشرح بالتفصيل كيفية العمل مع رموز JWT في PHP: بدءًا من تثبيت المكتبة إلى إنشاء الرموز والتحقق منها وتحديثها.
\n\nما هو JWT ولماذا هو مطلوب؟
\n\nيتكون JWT من ثلاثة أجزاء مفصولة بنقاط:
\n\n- \n
- Header (الرأس) — يحتوي على نوع الرمز (JWT) وخوارزمية التوقيع (مثل HS256 أو RS256). \n
- Payload (الحمولة) — يحتوي على الادعاءات (claims): معرف المستخدم، الدور، وقت الإصدار (iat)، تاريخ انتهاء الصلاحية (exp) وبيانات أخرى. \n
- Signature (التوقيع) — يتم إنشاؤه عن طريق تجزئة الرأس والحمولة باستخدام مفتاح سري. \n
المزايا الرئيسية لـ JWT:
\n- \n
- لا يتطلب تخزين الجلسات على الخادم (stateless). \n
- يمكن أن يحتوي على أي بيانات (مثل دور المستخدم). \n
- يعمل مع نطاقات مختلفة وتطبيقات الجوال. \n
- يمكن التحقق منه بسهولة دون الرجوع إلى قاعدة البيانات. \n
تثبيت مكتبة firebase/php-jwt
\n\nللعمل مع JWT في PHP، سنستخدم المكتبة الشهيرة firebase/php-jwt. يتم التثبيت عبر Composer:
composer require firebase/php-jwt\n\nبعد التثبيت، سيظهر في المشروع التحميل التلقائي لـ Composer، والذي يجب تضمينه:
\n\nrequire_once 'vendor/autoload.php';\n\nuse Firebase\\JWT\\JWT;\nuse Firebase\\JWT\\Key;\n\nإنشاء رمز JWT
\n\nلإنشاء رمز، يجب تحديد مفتاح سري ($secretKey) وتشكيل الحمولة. مثال:
use Firebase\\JWT\\JWT;\n\n$secretKey = 'your-256-bit-secret-key-here';\n$issuedAt = time();\n$expirationTime = $issuedAt + 3600; // الرمز صالح لمدة ساعة واحدة\n\n$payload = [\n 'iss' => 'pythonlib.ru', // الناشر\n 'iat' => $issuedAt, // وقت الإصدار\n 'exp' => $expirationTime, // تاريخ انتهاء الصلاحية\n 'sub' => 123, // معرف المستخدم\n 'role' => 'admin' // بيانات مخصصة\n];\n\n$jwt = JWT::encode($payload, $secretKey, 'HS256');\necho $jwt;\n\nستكون النتيجة سلسلة مثل: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJweXRob25saWIucnUiLCJpYXQiOjE3Mjg0MDAwMDAsImV4cCI6MTcyODQwMzYwMCwic3ViIjoxMjMsInJvbGUiOiJhZG1pbiJ9.signature
التحقق من JWT وفك تشفيره
\n\nعند استلام رمز من العميل (على سبيل المثال، من الرأس Authorization: Bearer <token>)، يجب التحقق منه:
use Firebase\\JWT\\JWT;\nuse Firebase\\JWT\\Key;\n\n$secretKey = 'your-256-bit-secret-key-here';\n$jwt = $_SERVER['HTTP_AUTHORIZATION'] ?? '';\n\ntry {\n $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256'));\n $userId = $decoded->sub;\n $role = $decoded->role;\n \n echo "المستخدم #{$userId} بدور {$role} مصرح به.";\n} catch (\\Exception $e) {\n http_response_code(401);\n echo "خطأ: " . $e->getMessage();\n}\n\nهام: تقوم المكتبة تلقائيًا بالتحقق من تاريخ انتهاء صلاحية الرمز (exp) ووقت الإصدار (iat). إذا كان الرمز منتهي الصلاحية أو غير صالح، سيتم طرح استثناء.
\n\nتحديث JWT (Refresh Token)
\n\nلتعزيز الأمان، عادةً ما تكون رموز JWT قصيرة العمر (15–60 دقيقة). للجلسات الطويلة، يُستخدم Refresh Token — وهو رمز منفصل يتم تخزينه في قاعدة البيانات ويسمح بالحصول على Access Token جديد دون إعادة إدخال اسم المستخدم وكلمة المرور.
\n\nمثال على تنفيذ التحديث:
\n\nfunction refreshAccessToken(string $ref