لماذا ينجح اختبار الواجهة وتفشل الخدمة؟
قد يختار المستخدم صورة صحيحة في نموذج ويب، ويرى شريط تقدم يصل إلى مئة بالمئة، ثم يفاجأ بأن الملف لا يظهر أو أنه ظهر لشخص آخر. وقد يقبل المتصفح امتداد JPG بينما يستقبل الخادم ملفًا مختلف المحتوى. لذلك لا تكفي تجربة رفع ملف واحد من واجهة جميلة، ولا يكفي التحقق من multipart/form-data. الهدف هنا بناء مصفوفة قبول واختبارات للملف من لحظة الاختيار حتى التخزين والفحص والعرض والتنزيل والحذف. هذا يختلف عن مقالات شرح بروتوكول رفع الملفات؛ نحن نراجع صلاحية العملية وحدود الثقة والتجربة تحت الفشل بأدلة قابلة لإعادة التنفيذ.
ارسم مسار الملف كاملًا
ارسم ست محطات واضحة: اختيار الملف، التحقق الأولي في المتصفح، استلام الخادم، التخزين المؤقت، فحص المحتوى، ثم الإتاحة للمستخدم المخول. لكل محطة حدد المسؤول وحالة الخطأ ورسالة الواجهة. لا تعتبر نجاح HTTP 200 إثباتًا لإتاحة الملف؛ ربما ما زال في طابور الفحص أو تعذر إنشاء المعاينة. سجل معرف ملف داخليًا يمكن تتبعه، لكن لا تعرض المسار الفعلي للتخزين للمستخدم. إذا كان هناك تخزين سحابي، وضح متى ينتهي النقل ومتى يصبح الملف جاهزًا. اختبر الحالات التي يتأخر فيها الفحص أو يعيد نتيجة غير حاسمة.
ضع سياسة أنواع مسموحة بحسب الحاجة
ابدأ من احتياج المنتج: صور JPEG و PNG لصور الحساب، أو PDF للمستندات، أو CSV للاستيراد. لا تقبل جميع الأنواع لمجرد أن النظام قادر على تخزينها. قارن اسم الملف والامتداد و Content-Type المرسل مع فحص المحتوى الحقيقي؛ كل إشارة منفردة قابلة للخطأ أو التلاعب. لا تجعل MIME الذي يرسله العميل قرارًا نهائيًا. إذا كان المنتج يقبل PDF، اختبر أن محلل PDF يستطيع فتح الملف وأن محتواه يلائم الاستخدام. وعند قبول صور، فك ترميزها وأعد إنشاء نسخة مناسبة إن كان ذلك جزءًا من السياسة. لا تدع اسم الملف يتحكم في مسار التخزين.
اختبر الحدود الرقمية قبل استهلاك الموارد
حدد حجمًا أقصى منطقيًا لكل نوع، وحدود عدد الملفات في الطلب، وحجم الحزمة الإجمالي، وحصة تخزين المستخدم إن وجدت. اختبر ملفًا أصغر من الحد بقليل، وملفًا مساويًا له، وآخر أكبر منه، ولا تنس حالات الحجم غير المعلن أو التدفق المتقطع. بعض الملفات المضغوطة صغيرة عند النقل لكنها تتمدد كثيرًا عند الفتح؛ لا تفك أرشيفًا غير موثوق دون قيود على الحجم وعدد الملفات والعمق. افصل رفضًا مبكرًا واضحًا عن فشل شبكة عابر. لا تجعل استجابة الخادم تكشف تفاصيل داخلية عن مسارات الملفات أو المكتبات المستخدمة.
صلاحيات الرفع والتنزيل والحذف
اختبر الصلاحية في الخادم وليس في زر مخفي فقط. أنشئ مستخدمين تجريبيين A و B، ثم حاول عرض ملف A أو حذفه من جلسة B. يجب أن يطبق الخادم سياسة الوصول على كل عملية، بما فيها إنشاء روابط معاينة مصغرة أو تنزيل نسخة معالجة. راجع أثر نقل الملف من مساحة خاصة إلى عامة، وهل يبقى الرابط القديم صالحًا بعد تغيير الصلاحية. إذا استُخدمت روابط موقعة قصيرة العمر، اختبر انتهاءها وإبطالها عند الحاجة. لا تستخدم بيانات أشخاص حقيقيين في الاختبارات؛ أنشئ ملفات اصطناعية لا تحتوي على معلومات خاصة.
الحجر المؤقت والفحص غير المتزامن
قد يستغرق فحص بعض الملفات وقتًا أطول من طلب HTTP عادي. لذلك عرّف حالات uploaded ثم scanning ثم ready أو rejected أو scan_failed. لا تتيح الملف العام قبل تحقق السياسة المطلوبة. إذا تعطل عامل الفحص، يجب أن تبقى حالة الملف غير الجاهز واضحة بدل اعتباره سليمًا. راقب عدد العناصر في الطابور ومدة انتظارها، وحدد طريقة إعادة الفحص أو التصعيد عند فشل أداة الفحص. لا تدّع أن مضاد الفيروسات يضمن سلامة كل ملف؛ إنه طبقة مساعدة ضمن سياسة أنواع وتخزين وعرض. اختبر كذلك عدم تشغيل المحتوى المرفوع على خادم التطبيق.
اسم الملف ليس مسار تخزين
اسم الملف الذي يختاره المستخدم قد يحتوي على رموز Unicode أو نقاط متكررة أو أسماء طويلة جدًا. احفظ الاسم الأصلي للعرض بعد تنقيته وتحديد طوله، لكن استخدم معرفًا يولده الخادم لتسمية الملف في التخزين. اختبر اسمًا عربيًا واسمًا إنجليزيًا طويلًا واسمًا بلا امتداد واسمًا فيه نقاط متعددة. عند تنزيل الملف، اضبط Content-Disposition و Content-Type بطريقة آمنة تناسب نوع المحتوى. لا تعتمد على حذف الشرطات المائلة فقط؛ راجع طريقة تعامل مكتبة التخزين مع المسارات. يجب أن يبقى الملف ضمن مساحة التخزين المخصصة له مهما كان الاسم المعروض.
واجهات المستخدم عند الخطأ والاستئناف
يجب أن يعرف المستخدم الفرق بين فشل الاختيار وفشل النقل وفشل الفحص بعد النقل. لا تعرض مئة بالمئة بمعنى جاهز إذا كانت النسبة تخص نقل البايتات فقط. ضع وصفًا نصيًا لحالة الرفع يصل إلى قارئ الشاشة، وزر إعادة المحاولة عندما تكون آمنة، وإلغاء واضحًا ينظف الحالة المؤقتة. إذا كان الرفع قابلًا للاستئناف، استخدم معرف جلسة رفع وتحقق من ترتيب الأجزاء وسلامتها قبل التجميع. لا تكرر ملفًا عند إعادة إرسال الجزء نفسه. واختبر فقد الاتصال ثم عودته، وإغلاق التبويب، وانتقال المستخدم إلى صفحة أخرى أثناء الفحص.
اختبر الملفات الصالحة غير المعتادة
لا ينبغي أن تتحول الحماية إلى رفض عشوائي لملفات سليمة. اختبر صورًا ذات اتجاه EXIF مختلف، وأسماء عربية، وملفات PDF بعدد صفحات متباين، و CSV بترميزات متعددة إذا كان المنتج يدعمها. تحقق من أن معالجة الصورة لا تقلب الاتجاه أو تغير الألوان بطريقة غير متوقعة. إذا كان هناك OCR أو استخراج نصوص، افصل نجاح التخزين عن نجاح الاستخراج. لا ترفض ملفًا لمجرد وجود بيانات وصفية إلا إذا كانت سياسة الخصوصية تقتضي ذلك، وفي هذه الحالة أخبر المستخدم بما سيزال. قارن نتيجة الملف الأصلي بالنسخة المشتقة مع حفظ سلامة الأصل حسب السياسة.
ماذا تقيس أثناء الاختبار؟
سجل معدل الرفض بحسب السبب، والوقت من اكتمال النقل إلى الجاهزية، ونسبة فشل المعاينة، وأخطاء الوصول غير المصرح، وعدد الملفات التي بقيت في الحجر. لا تضع أسماء الملفات الحساسة في لوحة عامة. راقب أيضًا استهلاك القرص والذاكرة وعدد العمال عند معالجة ملفات كبيرة؛ فالاختبار الناجح على ملف صغير لا يثبت استقرار الخدمة تحت الضغط. ابدأ بتزامن منخفض ثم ارفعه في بيئة اختبار مضبوطة، مع حد إيقاف عند ظهور تدهور. استخدم نتائج متكررة لتحديد العتبات، ولا تنقل أرقام مثال إلى الإنتاج دون قياس.
جدول سيناريوهات القبول
صنف الحالات إلى ملف مسموح سليم، وامتداد مضلل، وحجم زائد، وملف غير مصرح به، وانقطاع أثناء النقل، وفشل فحص بعد النقل، ومحاولة تنزيل من حساب آخر. لكل حالة سجل النتيجة المتوقعة في الواجهة والخادم وحالة الملف النهائية. على سبيل المثال، رفض الامتداد المضلل يجب أن يمنع الإتاحة، لا أن يغير اسم الملف ثم يسمح بعرضه. وفشل الفحص يجب أن يترك الملف غير متاح إلى أن يحسم القرار. استخدم معرف اختبار مستقل لكل ملف لتجنب خلط نتائج محاولات سابقة.
مصفوفة قبول نموذج رفع الملفات
| ملف مسموح | جاهز بعد الفحص | سجل ومحتوى |
| امتداد مضلل | رفض واضح | محتوى فعلي |
| حجم زائد | رفض مبكر | حدود النقل |
| مستخدم آخر | منع الوصول | صلاحيات الخادم |
| فشل فحص | غير متاح | حالة الحجر |
اختبارات الاستعادة والحذف
اختبر حذف ملف جاهز، ثم حاول الوصول إلى نسخه المشتقة مثل الصورة المصغرة والرابط المؤقت. راجع سلوك النسخ الاحتياطي والاحتفاظ وفق سياسة الخدمة، لأن حذف السجل من قاعدة البيانات لا يعني بالضرورة حذف كل نسخة فورًا. اختبر أيضًا إعادة رفع الملف نفسه: هل ينشئ نسخة مستقلة أم يتعرف على المحتوى؟ يجب أن تكون السياسة معلنة. عند فشل تخزين الملف بعد إنشاء السجل، لا تترك حالة جاهز بلا ملف. وعند نجاح التخزين وفشل قاعدة البيانات، وفر مهمة تنظيف ومصالحة. هذه الحالات تكشف أخطاء لا تظهر في الاختبار السعيد المعتاد.
قائمة إطلاق مختصرة
قبل النشر تحقق من سياسة الأنواع والأحجام، والتحقق من المحتوى لا الترويسة وحدها، وأسماء تخزين يولدها الخادم، وصلاحيات الرفع والعرض والحذف، والحجر والفحص عند الحاجة، وحالات واجهة مفهومة، وحدود المعالجة، وسجل يربط الملف بحالته. نفذ اختبارات على حسابين مستقلين، واختبر فشل عامل المعاينة وفشل التخزين، ثم راجع رسائل الأخطاء بالعربية والإنجليزية. لا تدّع أن أي اختبار يضمن خلو جميع الملفات من المخاطر؛ الهدف تخفيض المخاطر وتحسين قابلية الكشف والاستجابة. احتفظ بالسيناريوهات ونتائجها كوثيقة قبول قابلة للتحديث.
المراجع وروابط داخلية
مرجع OWASP الأساسي لرفع الملفات: https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html ، ومرجع التحقق من المدخلات: https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html . ولشرح مشكلات multipart/form-data الموجودة على إيجي تاج: https://egytag.com/ar/articles/multipart-form-data-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%B4%D8%A7%D8%A6%D8%B9%D8%A9-%D8%B9%D9%86%D8%AF-%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%B1%D9%81%D8%B9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA . تتغير المخاطر بحسب نوع الملفات والتطبيق والبنية؛ اتبع الوثائق الخاصة بمكتباتك وراجع حدود كل فحص بدل اعتباره حماية مطلقة.
شارك في تقييم ونقاش المقال
رأيك يضيف قيمة للمقال ويساعدنا على تحسين المحتوى والنقاش حوله.
النقاش
جارٍ تحميل التعليقات…