Express.js / الأساسي: مسؤولية الطلب والاستجابة / الدرس 5
تحليل الجسم والتحقق واختيار الحقول الآمنة
عامل التحليل كتعرف على الصياغة، وابن إدخال مجال صريحاً محدوداً قبل الكتابة.
في هذه الصفحة
أهداف الدرس
- افصل نوع المحتوى وحدود المحلل والتحقق البنيوي وقواعد المجال.
- ارفض القيم المخالفة أو المجهولة دون نسخ جسم الطلب كله إلى الكيان.
تبقى JSON المحللة إدخال تطبيق غير موثوق
تتعرف express.json على إدخال JSON المدعوم وفق خياراتها ونوع المحتوى المطابق. لا تثبت وجود title أو كونها سلسلة أو موافقتها للطول أو سماح تعديلها لهذه الهوية. في Express 5 قد تبقى req.body غير معرفة عندما لا يملأها محلل؛ لذلك عالج انطباق المحلل صراحة. ميز JSON المعيبة عن نوع المحتوى غير المدعوم والحجم الزائد وJSON الصحيحة ذات البنية المخالفة للمجال. صنف النتائج بعقد خطأ متسق لا يكشف التفاصيل الداخلية ولا يعامل الجسم المفقود كتحديث فارغ صحيح عن طريق الصدفة.
حدد نطاق المحلل وحد الكتابة
يركب الجزء محلل JSON محدوداً على مسار كتابة محدد، ثم يحول الجسم عبر دالة تحقق. الحجم اختيار تعليمي اصطناعي وليس حداً آمناً لكل التطبيقات. يجب أيضاً فرض حدود مناسبة عند مدخل النظام ومراعاة فك الضغط والتخزين الوسيط السابق. تتلقى الخدمة إدخال مجال اختير عمداً بدلاً من req.body الخام. وينبغي تثبيت المصادقة وتفويض الكائن قبل أي كتابة مسموحة. المثال جزء إطار غير مشغل؛ أما دالة التحقق المحلية المنفصلة فلا تقدم إلا دليل اختبار وظيفتها النقية، ولا تصادق حدود مدخل أو محلل HTTP فعلي.
app.post("/courses", express.json({limit:"8kb"}), async (req,res) => {
const input = validateCourseInput(req.body);
const course = await catalog.createFor(req.principal,input);
return res.status(201).json({id:course.id,title:course.title});
});
يفترض الجزء هوية مراجعة وخدمة catalog محقونة. يجب اكتمال التحقق قبل createFor، ولا يعرض الرد إلا الحقول المختارة.
حدد سياسة الحقول المجهولة والتطبيع صراحة
قد يسمح نسخ كل أعضاء الجسم للكيان بتغيير الدور أو المالك أو حالة النشر عبر حقول لم يقصد العنوان إتاحتها. حدد المفاتيح المسموحة واخترها وحدها. قرر هل ترفض المجهول أو تتجاهله، ووثق إزالة الفراغات وطريقة عد Unicode والسلسلة الفارغة. لا تغير قاعدة التحقق هوية أو صلاحية بصمت. وفي التحديث الجزئي قد تختلف دلالة غياب العضو وnull الصريحة والسلسلة الفارغة. اختبرها مستقلة بدلاً من فحص صدق يخلط الحذف والمسح، لأن هذا الفرق يحدد ما سيكتبه المجال فعلياً.
ابن إدخال مجال صغيراً صارماً
يطلب المحقق المحلي سجلاً من نمط كائن JSON يحتوي العضو المسموح الوحيد، وعنواناً بعد إزالة فراغات الطرفين من نقطة Unicode واحدة إلى ستين. يرفض المصفوفة وnull والمفاتيح المجهولة. عد نقاط Unicode سياسة عينة صريحة؛ فلا يدعي عد المحارف المرئية المركبة أو بايتات قاعدة البيانات. يعيد كائناً جديداً حتى تتلقى الخدمة عقداً ضيقاً. يغطي الاختبار التطبيع الصحيح ورفض الحقل المجهول والفراغ. قد يحتاج التطبيق مكتبة مخطط مراجعة وقواعد مجال إضافية، لكن ينبغي أن تظل قرارات حد الإدخال هذه واضحة.
function validateCourseInput(body) {
if (!body || typeof body !== "object" || Array.isArray(body)) throw new Error("INVALID_INPUT");
if (Object.keys(body).some(key => key !== "title")) throw new Error("UNKNOWN_FIELD");
if (typeof body.title !== "string") throw new Error("INVALID_TITLE");
const title = body.title.trim();
if ([...title].length < 1 || [...title].length > 60) throw new Error("INVALID_TITLE");
return {title};
}
console.assert(validateCourseInput({title:" HTTP foundations "}).title === "HTTP foundations");
for (const body of [{title:"X",owner:"other"},{title:" "},null,[]]) {
let rejected=false; try {validateCourseInput(body);} catch {rejected=true;}
console.assert(rejected);
}
يزيل المثال فراغات العنوان الصحيح. ترفض العينات الأربع باستثناء قبل وجود أي كتابة مجال؛ ولا يشغل النموذج express.json.
احفظ البايتات الخام حين يتطلبها البروتوكول
توثق بعض بروتوكولات الردود الموقعة بايتات الجسم الأصلية. قد يغير التحليل وإعادة تسلسل JSON المسافات أو التمثيل مع بقاء الكائن المنطقي نفسه، فلا يعوض ذلك البايتات الخام. اختر دمجاً محدود النطاق للجسم الخام أو التحقق يوافق البروتوكول الموثق، وتأكد من ألا يكون محلل آخر قد استهلك التدفق. لا تسجل التواقيع أو الأسرار أو الحمولات الخاصة كاملة أثناء التشخيص. يثبت تحقق الصياغة وفحص التوقيع ومنع الإعادة وتفويض المجال حقائق مختلفة، ويحتاج كل منها سلوك فشل محدوداً وواضحاً.
الأخطاء الشائعة وإصلاحها
تغير JSON صحيحة حقل مالك داخلي
- لماذا يحدث؟
- نسخ الجسم كله بدلاً من اختيار إدخال مسموح.
- كيف تصلحه؟
- حدد المفاتيح وأنشئ كائناً ضيقاً جديداً للمجال.
- كيف تتجنب تكراره؟
- اختبر أعضاء حساسة مجهولة مثل owner أو role.
تكون req.body غير معرفة
- لماذا يحدث؟
- لم يملأها محلل منطبق أو كان موضعه خاطئاً.
- كيف تصلحه؟
- افحص الطريقة والنوع والنطاق والترتيب قبل افتراض كائن فارغ.
- كيف تتجنب تكراره؟
- اختبر غياب الجسم ونوع المحتوى غير المدعوم صراحة.
يفشل توقيع الحمولة بعد إعادة بناء JSON
- لماذا يحدث؟
- استعمل التحقق نصاً معاداً بدل بايتات البروتوكول الأصلية.
- كيف تصلحه؟
- احفظ الوصول للجسم الخام المتحقق منه وفق عقد الدمج.
- كيف تتجنب تكراره؟
- اختبر اختلاف الفراغات وترتيب المحلل بعينات توقيع اصطناعية.
اختبر فهمك
1. لماذا يسمي المثال نقاط Unicode بدلاً من ادعاء عد المحارف المرئية؟
اعرض الحل المشروح
يمر نشر سلسلة JavaScript على نقاط Unicode، وقد يتكون المحرف الذي يراه المستخدم من عدة نقاط. وقد يقيد التخزين البايتات أيضاً. حدد المقياس واختبر نصوصاً متعددة اللغات، ولا تدع أن فحص طول محلياً يلبي كل متطلبات العرض والتطبيع والحفظ.
2. هل يصادق تحليل JSON ردّاً موقعاً أو يفوض تغيير حالته؟
اعرض الحل المشروح
لا؛ يتعرف التحليل على الصياغة وينشئ القيم. يربط التوقيع البايتات الأصلية المطلوبة بالمرسل وفق بروتوكوله، وتعالج ضوابط الإعادة تكرار التوصيل، وتقرر السياسة جواز التحول. افصل المراحل ولا تعتبر التحليل بديلاً عنها.
أهم ما تعلمته
- يتعرف التحليل على الصياغة، ويقرر التحقق والسياسة الإدخال المسموح.
- يمنع الإدخال الضيق المختار التعيين الجماعي العرضي.