رموز JWT في C++: مكتبة jwt-cpp
\n\nJSON Web Token (JWT) هي طريقة مضغوطة ومكتفية ذاتياً لنقل المعلومات بين الأطراف على شكل كائن JSON. في لغة C++، توجد عدة مكتبات للعمل مع JWT، لكن واحدة من أشهرها وأسهلها استخداماً هي jwt-cpp. توفر واجهة برمجة تطبيقات بسيطة لإنشاء وتوقيع والتحقق من رموز JWT باستخدام خوارزميات مختلفة (HMAC، RSA، ECDSA).
\n\nفي هذه المقالة، سنستعرض الإمكانيات الأساسية لمكتبة jwt-cpp، ونتعلم كيفية إنشاء الرموز والتحقق منها، بالإضافة إلى تحليل أمثلة كود للمهام النموذجية.
\n\nتثبيت jwt-cpp
\n\nمكتبة jwt-cpp هي مكتبة رؤوس فقط (header-only)، مما يبسط دمجها في المشروع. للتثبيت، يكفي استنساخ المستودع:
\n\ngit clone https://github.com/Thalhammer/jwt-cpp.git\n\nثم أضف المسار إلى مجلد include في إعدادات المترجم الخاص بك. إذا كنت تستخدم CMake، سيكون الربط على النحو التالي:
add_subdirectory(jwt-cpp)\ntarget_link_libraries(your_project jwt-cpp)\n\nتعتمد المكتبة على OpenSSL و jsoncpp (أو nlohmann/json)، لذا تأكد من تثبيتهما.
إنشاء رمز JWT أساسي
\n\nأبسط مثال هو إنشاء رمز باستخدام خوارزمية HMAC-SHA256. يمكن إضافة الحقول القياسية (iss، sub، exp، iat) وأي claims مخصصة إلى الرمز.
\n\n#include <jwt-cpp/jwt.h>\n#include <iostream>\n\nint main() {\n // إنشاء الرمز\n auto token = jwt::create()\n .set_issuer("auth0")\n .set_subject("1234567890")\n .set_issued_at(std::chrono::system_clock::now())\n .set_expires_at(std::chrono::system_clock::now() + std::chrono::hours{1})\n .set_payload_claim("name", jwt::claim(std::string("John Doe")))\n .sign(jwt::algorithm::hs256{"secret-key"});\n\n std::cout << "الرمز: " << token << std::endl;\n return 0;\n}\n\nالنتيجة ستكون سلسلة مكونة من ثلاثة أجزاء (header، payload، signature) مفصولة بنقاط.
\n\nالتحقق من الرمز
\n\nللتحقق من صحة الرمز، يجب استخدام نفس المفتاح السري (أو المفتاح العام لـ RSA). مثال على التحقق:
\n\n#include <jwt-cpp/jwt.h>\n#include <iostream>\n\nint main() {\n std::string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."; // رمزك\n\n try {\n auto decoded = jwt::decode(token);\n \n // التحقق من التوقيع\n auto verifier = jwt::verify()\n .allow_algorithm(jwt::algorithm::hs256{"secret-key"})\n .with_issuer("auth0");\n\n verifier.verify(decoded);\n\n // استخراج البيانات\n std::cout << "الرمز صالح!" << std::endl;\n std::cout << "الموضوع: " << decoded.get_subject() << std::endl;\n std::cout << "الاسم: " << decoded.get_payload_claim("name").as_string() << std::endl;\n } catch (const std::exception& e) {\n std::cerr << "خطأ في التحقق: " << e.what() << std::endl;\n }\n\n return 0;\n}\n\nهام: إذا كان الرمز منتهي الصلاحية (exp)، أو تم تعديله، أو تم توقيعه بمفتاح آخر، سيتم إلقاء استثناء.
\n\nالعمل مع RSA (التشفير غير المتماثل)
\n\nللأنظمة الأكثر أماناً، غالباً ما يُستخدم RSA. في هذه الحالة، يتم توقيع الرمز بمفتاح خاص، والتحقق منه بمفتاح عام.
\n\n#include <jwt-cpp/jwt.h>\n#include <fstream>\n#include <sstream>\n\nint main() {\n // قراءة المفتاح الخاص من ملف\n std::ifstream priv_file("private.pem");\n std::stringstream priv_ss;\n priv_ss << priv_file.rdbuf();\n std::string private_key = priv_ss.str();\n\n // إنشاء رمز باستخدام RSA\n auto token = jwt::create()\n .set_issuer("myapp")\n .set_subject("user123"