سرور رزرو همان سینما، پنج درخواست پشت سر هم میگیرد و پنج جواب متفاوت میدهد. کل ماجرای این صفحه در همین پنج سطر است:
GET /salonجواب ۲۰۰GET /sandali/Z9جواب ۴۰۴POST /rezervبدون کوکی، جواب ۴۰۱POST /voroodجواب ۳۰۳ بهعلاوه یکSet-CookiePOST /rezervبا همان کوکی، جواب ۲۰۰
هندلر تابعی است از یک درخواست به یک جواب، و هیچ چیز دیگری. مسیر هم روش و نشانی با هم است، نه نشانی بهتنهایی، پس GET /rezerv و POST /rezerv دو مسیر جدا هستند و میتوانند دو کد وضعیت متفاوت بدهند. تفاوت دو کد بالا هم دقیقاً همین را میگوید: ۴۰۴ یعنی هیچ مسیری تطبیق نکرد، و ۴۰۱ یعنی مسیر تطبیق کرد و شما وارد نشدهاید. اشتباه گرفتن این دو، خطای رایج یک سرویس تازه است و نتیجهاش این است که کاربر بهجای «وارد شوید» میبیند «پیدا نشد».
سطر چهارم آن یکی است که همه از رویش میپرند. ۳۰۳ بعد از یک POST مرورگر را به یک GET میفرستد، پس تازه کردن صفحه دوباره ارسال نمیکند. بدون آن، کاربری که بعد از رزرو صفحه را رفرش میکند دو صندلی رزرو کرده است، و هیچ چیزی در کد جلویش را نگرفته.
کوکی تنها دلیلی است که درخواست دوم شما را میشناسد
HTTP بیحالت است، پس کوکی تنها دلیلی است که درخواست دوم شما را میشناسد. سرور میان آن دو POST هیچ چیزی از شما به یاد ندارد؛ چیزی که فرق کرده این است که مرورگر یک شناسه را نگه داشته و بیآنکه از او خواسته شود پس فرستاده. سه صفت روی همان کوکی سه خانواده حمله را میبندند و هر سه بهطور پیشفرض خاموشاند:
HttpOnlyکوکی را از دسترس جاوااسکریپت دور نگه میداردSecureیعنی کوکی فقط روی https فرستاده میشودSameSite=Laxجلوی سوار شدن کوکی روی درخواستی از یک سایت دیگر را میگیرد
و قاعدهای که زیر هر سه است: کوکی یک شناسه نگه میدارد و سرور خودِ نشست را، پس هیچ چیز محرمانهای سفر نمیکند. اگر کوکی خودش بگوید کاربر کیست یا چه اجازههایی دارد، آن حرف را کسی نوشته که کنترلش دست شما نیست. همین شکل، موضوع اینکه یک پروتکل بیحالت چطور شما را به یاد میآورد است، و تصمیمهای دور و برش وارد شدن، وارد ماندن، و انجام دادنش بهشکل امن.
یک نکته عملی برای اینجا: Secure بدون گواهی https کوکی را اصلاً نمیفرستد، و روی سرویسهای ایرانی که پشت یک CDN داخلی نشستهاند، اتصال میان CDN و سرور شما ممکن است http ساده باشد در حالی که کاربر https میبیند. آن وقت کوکی سر میخورد و ورود کار نمیکند، بدون هیچ خطایی جز اینکه کاربر همیشه بیرون است. این را باید در تنظیمات پیشوند اعتماد سرور حل کرد نه با برداشتن آن صفت.
پنج ایستگاه، و همان پنجتا در هر زبانی
درخواست میرسد، مسیر تطبیق میشود، فراخوان شناسایی میشود، کار انجام میشود، جواب برمیگردد. تنها ایستگاهی که به چیزی ماندگار دست میزند چهارمی است، و همه چیزی که باید بعد از این درخواست زنده بماند همانجا نوشته میشود. نگاشت یک نشانی به کدی که جوابش میدهد نگاشت یک URL به کدی که جوابش میدهد است، و همین پنج ایستگاه کاملتر در درخواست داخل، جواب بیرون، و هر چه میانشان است.
چه کسی چه چیزی را نگه داشته
ضلعی از این مثلث که کسی رسمش نمیکند
بازدیدکننده به ضلع اول فکر میکند. هر پرسشی درباره وارد شدن و وارد ماندن و بیرون انداخته شدن، روی ضلع دوم تصمیم گرفته میشود.
- یک کوکی، فرستادهشده روی هر درخواست
- روی هر درخواست خوانده میشود، و میشود پاکش کرد
- هیچ چیزی درباره بازدیدکننده از این راه سفر نمیکند
- مرورگر
- سرور
- انبار نشست
- مرورگریک شناسه را داخل یک کوکی نگه میدارد و بیآنکه از او خواسته شود پس میفرستد
- سرورهیچ خاطرهای از درخواست قبلی ندارد
- انبار نشستنگه میدارد که sid=s-1 واقعاً کیست، و میتواند در یک سطر فراموشش کند
- مرورگر — سروریک کوکی، فرستادهشده روی هر درخواست
- سرور — انبار نشستروی هر درخواست خوانده میشود، و میشود پاکش کرد
- انبار نشست — مرورگرهیچ چیزی درباره بازدیدکننده از این راه سفر نمیکند
نشست را به گوشه سوم ببرید و بیرون انداختن کسی میشود پاک کردن یک سطر. نگهش دارید داخل کوکی و بیرون انداختن، خواهشی از مرورگر است.
ابزار، و سالی که این حرف درست است
Node و ماژول HTTP خودش رایگان و متنباز است و جای این را گرفت که برای اجرای هر جاوااسکریپتی روی سرور به یک فرایند وبسرور جدا نیاز باشد. برای همین هم پنج درخواست بالا را میشود بدون هیچ فریمورکی نوشت، که برای یاد گرفتن بهتر است، چون هر پنج ایستگاه دیده میشوند. آن هم جاوااسکریپت روی سرور است.
یک کلاینت درخواست با مجموعه ذخیرهشده، جای تایپ کردن یک دستور curl از حفظ را میگیرد، و نسخههای رایگان و آفلاینش هست، که اینجا مهم است چون ابزارهای ابری این دسته معمولاً حساب و پرداخت میخواهند. لاگ ساختاریافته بهشکل JSON هم جای چاپ کردن یک جمله را گرفت، که وقتی چهار سرویس در کار باشد قابل ردیابی نیست، و کتابخانه رایگانش در هر زبان این صفحه هست.
اشتباه: باور کردن چیزی که درخواست درباره خودش میگوید
گیر واقعی اینجا نه مسیریابی است و نه کوکی. این است که درخواست میتواند بگوید فراخوان چه میخواهد، هرگز نمیتواند بگوید چه چیزی درست است. بدنه یک POST را کاربر تایپ کرده، و اگر داخلش فیلدی به نام karbar_id باشد و سرور به آن تکیه کند، هرکسی میتواند به نام هرکسی رزرو کند.
نسخه اول آن سرور سینما دقیقاً همین کار را کرد، و از بیرون هیچ فرقی با نسخه درست نداشت: همان صفحه، همان جواب ۲۰۰، همان رزرو. تفاوت فقط در این بود که هویت از یک فیلد بدنه خوانده میشد بهجای از نشستی که کوکی به آن اشاره میکند. قاعدهای که تمامش میکند یک جمله است و در ایستگاه سوم آن نقشه بالا نشسته: هویت فقط از نشست میآید، و هر چیز دیگری که در درخواست هست ورودی است، حتی وقتی خودش را هویت مینامد.
خانواده کامل این حملهها و باقیشان زیر وب است، و جایی که آن رزرو واقعاً نوشته میشود پایگاه داده. صفحهای هم که این جوابها را به کاربر نشان میدهد فریمورکهای فرانتاند است.