اذهب إلى المحتوى

السؤال

نشر

السلام عليكم،

في تطبيقات React.js، موضوع الحماية دائمًا من الأمور الحساسة والمهمة، وفي الغالب يكون الأسلوب المستخدم كالتالي:

بعد تسجيل الدخول أو إنشاء مستخدم جديد، نقوم بالحصول على Token ثم نخزنه في الذاكرة المحلية مثل localStorage أو cookies.
لكن للأسف، هذه الطريقة ضعيفة من ناحية الحماية، لأنها معرضة لهجمات مثل XSS (Cross-Site Scripting).

الطريقة الثانية هي حفظ بيانات المستخدم في الذاكرة المؤقتة (in-memory) داخل كائنات React، مما يوفر حماية أكبر لأن البيانات لا تُخزن في المتصفح بشكل دائم، ولكن المشكلة هنا أن هذه البيانات تُفقد بمجرد تحديث الصفحة أو إعادة تحميلها.

الحل الوسط الذي وجدته هو التالي:

في النظم الخلفية (Backend)، ننشئ Token محمي باستخدام httpOnly cookie، بحيث لا يمكن الوصول إليه من جافاسكريبت في المتصفح، مما يقلل خطر هجمات XSS.

مثال على إنشاء Token وتخزينه كـ httpOnly cookie:

const generateToken = (res, userId) => {
  const token = jwt.sign({ userId }, process.env.JWT_SECRET, {
    expiresIn: '30d',
  });

  // تعيين الـ JWT كـ httpOnly cookie
  res.cookie('jwt', token, {
    httpOnly: true,
    secure: process.env.NODE_ENV !== 'development', // لتأمين الكوكيز في بيئة الإنتاج
    sameSite: 'strict', // لمنع هجمات CSRF
    maxAge: 30 * 24 * 60 * 60 * 1000, // مدة 30 يومًا
  });

  return token;
};

ثم ننشئ نقطة نهاية (endpoint) لاسترجاع بيانات المستخدم مع بعض المعلومات الضرورية، مثل:

const getMe = asyncHandler(async (req, res) => {
  const user = await User.findById(req.user._id).select('-password');

  // استرجاع التوكن من الكوكيز
  const token = req.cookies.jwt;

  res.json({
    _id: user._id,
    name: user.name,
    email: user.email,
    isAdmin: user.isAdmin,
    token, // نُرسل التوكن أيضاً للواجهة الأمامية
  });
});

في الواجهة الأمامية، سأستخدم مكتبة tanstack query، التي توفر طريقة مرنة وفعالة للتعامل مع الـ API، مع دعم مدمج للـ caching.

سأقوم بجلب بيانات المستخدم من نقطة النهاية getMe وأحتفظ بها في الذاكرة (in-memory) داخل React. بهذه الطريقة نحقق التوازن بين:

  • حماية البيانات لأن التوكن مخزن كـ httpOnly cookie غير قابل للوصول من جافاسكريبت مباشرةً.
  • سهولة الوصول المستمر للبيانات في الواجهة الأمامية بدون فقدانها عند تحديث الصفحة.

يسعدني جداً سماع آرائكم وملاحظاتكم، فهذه الطريقة نابعة من فكرة محلية، وبالتالي فكل ملاحظة منكم قيمة وستفيدني كثيرًا في تحسين الأمان والأداء.

شكرًا لكم!

Recommended Posts

  • 0
نشر

وعليكم السلام ورحمة الله وبركاته،
الفكرة التي طرحتها جيدة وتجمع بين الأمان وسهولة الاستخدام، لأن تخزين التوكن في httpOnly cookie يحميه من هجمات XSS، وفي نفس الوقت الاحتفاظ ببيانات المستخدم في الذاكرة باستخدام tanstack query يمنع فقدانها أثناء العمل.
يمكن ايضاً التأكد من حماية الـ API من هجمات CSRF باستخدام إعدادات sameSite أو إضافة CSRF token.

بالتوفيق

  • 0
نشر

لديك خلط بسيط بين المفاهيم في نقطة getMe، قمت بإعادة إرسال الـ Token في الـ Response، أي أن التوكن سيُخزن مرة أخرى في الذاكرة React state، وذلك يُلغي ميزة استخدام httpOnly cookie، فالآن لديك نسخة من التوكن في JavaScript معرضة لـ XSS، ولم تعد بحاجة إلى إرسال التوكن في الـ Response، لأن الكوكي يُرسل تلقائيًا مع كل طلب.

فلا ترسل التوكن في الـ Response، فكل طلب إلى الـ Backend سيُرفق به الكوكي تلقائياً بما أن التوكن في httpOnly cookie.

وطلب getMe عند تحميل التطبيق أو عند الحاجة، وستستخدم TanStack Query لتخزين بيانات المستخدم فقط وليس التوكن.

وفي حال تستخدم Next.js أو SSR، فستحتاج إلى التأكد من أن الكوكي يُرسل من السيرفر إلى الـ API أيضاً بواسطة req.headers.cookie أو getServerSideProps مع withCredentials.

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...