الفجوة بين استخدام شيء وفهمه
في بداية مسيرتي المهنية، كنت أصحح خطأ في المصادقة عندما سأل مطور أول: «هل انتهت صلاحية JWT؟»
قلت نعم، لقد تحققت. ما لم أعترف به: كنت قد لصقت الرمز في موقع ويب، رأيت الطابع الزمني لانتهاء الصلاحية، ولم أكن أفهم تمامًا ما كنت أنظر إليه. هل كان آمنًا؟ هل يمكن لأحد قراءة هذا الرمز؟ هل كان مشفرًا؟ لماذا يمكن لأي موقع ويب فكّه إذا كان يُفترض أنه «موقّع» و«آمن»؟
هذا الدليل مكتوب لذلك الإصدار المبكر مني. ثلاثة مفاهيم تظهر باستمرار في تطوير الويب، تفترض معظم الدروس التعليمية أنك تعرفها مسبقًا، وهي في الواقع بسيطة متى شُرحت بوضوح.
Base64: ليس تشفيرًا. ليس ضغطًا. مجرد ترجمة.
أهم شيء يجب معرفته أولًا: Base64 ليس آلية أمان. لا يخفي بياناتك. يمكن لأي شخص فكّه فورًا. إذا فكرت يومًا «هذا يبدو مرمّزًا إذًا من المحتمل أن وضعه في URL آمن» — فهو ليس كذلك.
Base64 طريقة لتمثيل البيانات الثنائية باستخدام أحرف ASCII قابلة للطباعة فقط. هذا كل شيء. السبب العملي لوجوده: البيانات الثنائية تكسر الأشياء. رسائل البريد الإلكتروني ورؤوس HTTP وعناوين URL وسمات HTML — هذه الأنظمة صُممت للنص. البيانات الثنائية الخام ببايتاتها الصفرية وأحرفها الضابطة يمكن أن تتلف أو تتغير عند مرورها عبر أنظمة قائمة على النص.
Base64 يحول الثنائي إلى أبجدية آمنة من 64 حرفًا: A-Z وa-z و0-9 و+ و/. الإخراج أكبر بحوالي 33% من المدخل، لكنه مضمون أن يصل سليمًا عبر أي نظام نصي.
أين ستصادفه فعلًا
مصادقة HTTP الأساسية: عند المصادقة بـاسم_المستخدم:كلمة_المرور، تُرمَّز بيانات الاعتماد بـBase64 وترسل في رأس Authorization: Basic. لهذا السبب تعد مصادقة Basic على HTTP العادي خطرة — أي شخص يعترض الطلب يمكنه فكّ بيانات الاعتماد فورًا. HTTPS إلزامي.
رموز JWT: كل قسم من الأقسام الثلاثة لرمز JWT مرمّز بـBase64url (نوع يستبدل + و/ بـ- و_ ليكون آمنًا في URL).
Data URIs: <img src="data:image/png;base64,iVBORw0KGgo..."> — تضمين بيانات الصورة مباشرة في HTML أو CSS بدلًا من طلب HTTP منفصل.
مرفقات البريد الإلكتروني: ترميز MIME يستخدم Base64 حتى تتمكن الملفات الثنائية من السفر عبر خوادم بريد مصممة للنص فقط.
جرّب بنفسك: الصق أي نص في مرمّز Base64 وشاهد النتيجة. ثم الصق السلسلة المرمّزة مرة أخرى لفكّها. لاحظ أن النسخة «المرمّزة» لا تخفي شيئًا — تستخدم أبجدية مختلفة فحسب.
JWT: ثلاث سلاسل Base64 وتوقيع
رمز JSON Web يبدو هكذا:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJleHAiOjE3MTM5MzYwMDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
نقطتان بالضبط. ثلاثة أقسام.
الرأس — الجزء قبل النقطة الأولى. يُفكّ إلى بيانات وصفية عن الرمز: أي خوارزمية توقيع استُخدمت، ما نوع الرمز.
الحمولة — القسم الأوسط. يُفكّ إلى المطالبات الفعلية: معرف المستخدم والبريد الإلكتروني والأدوار ووقت الانتهاء. هذا ما يقرأه الخادم الخلفي للتعرف على المستخدم.
التوقيع — الجزء بعد النقطة الثانية. دليل تشفيري على عدم العبث بالرمز.
ما يفاجئ معظم المطورين
الحمولة مرمّزة بـBase64url. ليست مشفرة تشفيرًا قويًا. أي شخص يملك الرمز يمكنه فكّ الحمولة وقراءة محتواها — معرف المستخدم والبريد الإلكتروني والأدوار ووقت الانتهاء وأي شيء وضعته هناك.
الصق أي JWT في فكّاك JWT وشاهد بالضبط ما بداخله. لا حاجة لأي مفتاح.
هذا يفاجئ الناس لأن السلسلة تبدو كرمز غامض غير مفهوم. لكنها ليست كذلك. نموذج أمان JWT هو: «يمكنني التحقق من أن هذا الرمز أُصدر فعلًا من خادمي (التحقق من التوقيع)، لذا يمكنني الوثوق بالمطالبات التي يحتويها. لكن تلك المطالبات نفسها ليست سرية.»
التداعي العملي: لا تضع كلمات المرور وبيانات الدفع والمعلومات الشخصية الحساسة في حمولات JWT. ضع فقط ما هو ضروري لتحديد المستخدم والتحقق من صلاحياته.
ما يضمنه التوقيع فعلًا
يُنشأ التوقيع بأخذ الرأس + الحمولة + مفتاح سري يعرفه خادمك فقط، وتمريرها عبر دالة تجزئة. عندما يستقبل خادمك رمزًا، يعيد حساب التوقيع بالمفتاح السري ذاته. إذا تطابق التوقيع المُعاد حسابه مع ذلك الموجود في الرمز، فالرمز أصيل وغير معدّل.
إذا غيّر شخص ما الحمولة لتغيير معرف المستخدم من 123 إلى 456، يفشل التحقق من التوقيع.
لهذا يجب أن يظل مفتاح توقيع JWT الخاص بك سريًا فعلًا. إذا حصل عليه مهاجم، يمكنه تزوير الرموز وانتحال هوية أي مستخدم.
التجزئة: دوال الاتجاه الواحد
دالة التجزئة تأخذ أي مدخل وتنتج مخرجًا بحجم ثابت. خاصيتان تجعلانها مفيدة للأمن:
حتمية: نفس المدخل ينتج دائمًا نفس المخرج.
اتجاه واحد: لا يمكنك عكس التجزئة للحصول على المدخل الأصلي. لا وجود لـunhash().
SHA-256("كلمة_المرور123") → ef92b778bafe771207...
SHA-256("كلمة_المرور124") → 88d4266fd4e6338d13...
حرف واحد مختلف. تجزئة مختلفة تمامًا. لا علاقة رياضية بين مدخلات متشابهة ومخرجات متشابهة.
لماذا تُجزَّأ كلمات المرور ولا تُشفَّر
لو شُفِّرت كلمات المرور، يمكن فكّها بالمفتاح الصحيح. لو سرق مهاجم قاعدة بياناتك ومفتاح التشفير، تنكشف كلمة مرور كل مستخدم.
مع التجزئة: تخزّن التجزئة لا كلمة المرور. عندما يسجّل مستخدم دخوله، تجزّئ ما كتبه وتقارنه بالتجزئة المخزنة. لا تحتاج استرداد الأصل أبدًا — فقط التحقق من محاولة.
حتى لو حصل مهاجم على قاعدة بياناتك، لديه تجزئات فقط. للحصول على كلمة مرور، يجب تخمينها والتحقق منها، وهذا أبطأ بكثير.
MD5 وSHA-256 وbcrypt — لماذا يهم أيها تستخدم
MD5 كان المعيار في مطلع الألفية. الآن انكسر للأغراض الأمنية. وحدة معالجة رسومية حديثة يمكنها حساب مليارات تجزئات MD5 في الثانية، ما يعني أن مهاجمًا لديه قاعدة بياناتك يمكنه كسر كلمات المرور البسيطة في دقائق. لا تستخدم أبدًا MD5 لكلمات المرور.
SHA-256 مناسب للتحقق من السلامة — تأكيد عدم تلف ملف، توليد توقيعات HMAC لـwebhooks. لكنه سريع جدًا لكلمات المرور. السرعة سيئة لكلمات المرور لأنها تجعل هجمات القوة الغاشمة رخيصة.
bcrypt مصمم خصيصًا لكلمات المرور. بطيء عمدًا — يمكنك ضبط عدد جولات الحساب — ويتضمن «ملحًا» مدمجًا (بيانات عشوائية) يضمن أن كلمتي مرور متطابقتين تنتجان تجزئتين مختلفتين تمامًا.
القاعدة: استخدم bcrypt (أو Argon2 أو scrypt) لكلمات المرور. استخدم SHA-256 لكل شيء آخر يحتاج التحقق من السلامة.
مرجع سريع
| المفهوم | ما هو | قابل للعكس؟ | الاستخدام |
|---|---|---|---|
| Base64 | ترميز ثنائي → نص | نعم، بتفاهة | نقل البيانات الثنائية عبر أنظمة النص |
| JWT | رمز JSON موقّع | الحمولة: نعم. التوقيع: لا | المصادقة عديمة الحالة |
| SHA-256 | دالة تجزئة | لا | سلامة الملفات، توقيعات HMAC |
| bcrypt | تجزئة كلمات المرور | لا | تخزين كلمات مرور المستخدمين |
فهم هذه الأشياء الثلاثة بشكل صحيح يمنع فئة من أخطاء الأمن التي تبدو صحيحة في مراجعة الكود ولا تُكتشف إلا في الإنتاج — حين يكون الضرر قد وقع.
الأدوات: Base64، فكّاك JWT، مولّد Hash. استخدمها لاختبار فهمك، ليس فقط للحصول على نتائج.