درست کردن لینک دانلود یکبار مصرف + همراه محدودیت IP + و زمان داخل جنگو

خیلی مواقع نیازه که کلاینت بتونه به یکسری فایل که روی سرور هستن دسترسی پیدا بکنه بدون ادرس دهی مستقیم و یا تو یک بازمه زمانی خاصی دردسترسشون باشه این فایله . ولی ویط یکسری مشکلات هستش, لینک فایل کاربر ممکنه پخش بکنه بقیه کاربرا بدون خریدن اون فایل بهش دسترسی پیدا بکنن اگه اون فایل خریدنی هستش و هزار یک دلیل دیگه که خدا میدونه ولی چیزی که باعث شد من نیازش پیدا بکنم این بود که تو یک پروژه iot نیاز بود دستگاها بتونن خودشونو اپدیت بکنن برای همین یک لینک نیاز بود که اخرین ورژن سورس دستگاه اونجا باشهو اینا از اونجا خودشنو اپدیت کنن ولی یک مشکل امنیتی کوچولو این وسط بودش !. اگه شخص سومی این لینک سورس دستگاهی که برای اپدیت بود بدست میاورد میتونست اخرین ورژن سورس دستگاها دانلود بکنه .برای همین اومدم یک مکانیزم درست کردم که لینک غیر مستقیم به دستگاه سورس بدم و این لینک مخصوص همون دستگاهی باشه که اونو درخواست کرده بود و تو همون یک دقیقه معتبر باشه و اگه شخص سومی سعی میکرد لینک باز بکنه پیغام اینکه همچین صفحه وجود نداره برو هنوز واست زود مواجه بشه.خب از این حرفا بگذریم بیایم اینو تو یک پروژه پیاده سازی کنیم

نوشتن مکانیزم :

خب تو اولین قدم میایم پروژه جدید شروع میکنیم و توش یک آپ جدید میسازیم

خب ساختار پروژه میتونید ببینید الا وقته آپ جدید تو ستینگ اضافه کنیم

بعد اینکار نیازه که یک مدل برای بخش لینک های یکبار مصرف خودمون بسازیم به فایل models.py داخل آپ auth_system میریم و یک مدل شبیه عکس پایین میسازیم


خب بیایم مدل بالا ی تحلیل ریز بزنیم اول ی مدل به اسم Temp_link درست کردیم توش چهارتا فلید داریم

فیلد link :

این فلید از نوع UUIDFIELD هستش که توانای ذخیره uuid هارو داره و از این فلید برای ساخت لینک های تصادفی و غیر قابل حدس برای فایلم هامون استفاده میکنیم همینطور که میبیند این فیلد چندتا خصوصیت داره اولیش غیرقابل ادیت بودن لینکش هستش که editable=False این وظیفه بعهده داره.بعدیش کلید اصلی بودن هستش که بصورت پرامیری کی تعریف شده و یونیک بودن که این کارا دوتا ارگومان primary_key=True unique=True بعهده دارن . اخرین و مهمترینش جنریت شدن بصورت خودکار هستش برای همین از default استفاده کردیم و مقدارشو مساوی با uuid4 که از ماژول uuid ایمپورت شده قرار دادم و هر وقت uuid4 صدا زده بشه یک uuid ورژن 4 بهمون میده

فیلد expire :

این فیلد وظیفه تعیین زمان منقضی شدن لینک هارو بعهده داره برای همین از نوع DateTimeField استفاده کردم و مقدار پیش فرضشو مساوی قرار دادم با متد make_expire_time این متد میاد زمان حال میگیره و یک دقیقه بهش اضافه میکنه و تو فیلد قرار میده برامون بصورت پیش فرض اگه میخواهید زمان کمتر یا بیشتر کنید فقط مقدار timedelta تغییر بدید ورودی هاش میتونن minutes ,seconds ,hours ,days باشن هرکدوم نیاز دارید بزارید توش و مقدار بدید :)

فیلد ip :

این فیلد وظیفه نگهداری ip کلاینتی که درخواست دانلود اون فایل داده داره و هر وقت کلاینت از این لینک بخواد استفاده بکنه ما میایم و ip کسی که الا میخواد دانلود بکنه با ip کسی که این لینک براش ساختیم چک میکنیم و نوع این فیلد GenericIPAddressField هستش که ip ورژن 4 و 6 میتونه سیو کنه

فیلد file :

ما از این فیلد به عنوان رفرنس استفاده میکنیم حالا منظورم چیه ؟ فیلد FileField میتونه چند نوع ورودی بگیره یکیش ادرس فایل هستش اون یکیم یک instance از یک FileField دیگه هستش. حالا ما میایم یک فیلد FileField از داخل یک مدل دیگمون که قراره اون فایل دانلود بکنه یوزر بهش پاس میدیم

خب فیلد هامون تمام شد رسیدیم به یک متد مدل که از اسمش میتونید حدس بزنید چیکار میکنه درواقع متد check_expired میاد زمان حال به زمانیکه تو فیلد expire ذخیره شده برسی میکنه اگه زمان گذشته باشه False برمیگردونه و اگرم نه True و متد بعدی یعنی check_ip هم مثل قبلی میاد ip سیو شده با ip دریافتی برسی میکنه اگه یکی بودن True ریترن میکنه

خب حالا چطور استفاده کنیم ازش ؟

خب بیاید فرض کنیم شما یک آپ فروشگاه دارید که توش pdf میفروشید و ی مدل به این شکل دارید که pdf هارو توش ذخیره میکنید

store/models.py
store/models.py

حالا دیگه زیاد وارد جزییاتش نشید :))

حالا کاربر اومده ی پرداختی داشته و شما میخواهید اجازه بدید که دانلود بکنه pdf خب برای درست کردن لینک دانلودش این مراحل طی کنید

shell
shell

خب تو خط یک و دو اومدیم دوتا مدل خودمونو ایمپورت کردیم یک مدل مدل لینک های یکبار مصرفمون هستش و مدل دوم مدلی هستش که فایل دانلودی مون توش قرار داره

تو خط سه اومدیم یکی از این رکورد های داخل مدل PDF انتخاب کردیم حالا شما اینو وابسته به خرید کاربر ها هرطوری صلاح میدونید انتخاب میکنید .

تو خط چهار و پنج اومدم نشون دادم مقادیر داخل اون رکورد انتخاب شده همینطور که میبینید یک فیلد به اسم name و file که از نوع FileField هستش داره و فایل دانلودمون توش قرار داره

تو خط شیش اومدیم یک نمونه از مدل Temp_link درست کردیم که برامون کار درست کردن لینک های یکبار مصرفو داره و ورودی اولش ip کاربری که اون لحظه خرید انجام داده یا میخوایم اجازه استفاده از لینک بدیم بهش میدیم این ip میتونید از داخل request ویو بدست بیارید , ورودی file هم همینطور که بالاتر گفتم میایم فیلد فایل اون مدلی که میخوایم طرف فایل داخلشو دانلود بکنه میدیم اینجا اون فایل داخل مدل pdf ما هستش

تو خط هفت لینک یکبار مصرف سیو کردیم . تو خط هشت لینک اونو گرفتیم و تو خط نو هم زمانی منقضی شدن میبنیم و تو خط ده هم متدی که وظیفه برسی اینکه هنوز لینک زمانش معتبره یا نه داریم که اینجا False برگشت داده یعنی هنوز معتبره و تو خط ده یکبار اومدیم برسی کردیم ip کاربری که میخواد دانلود بکنه برسی کردیم دیدم که با اون چیزیکه انتظار ما بودش متفاوته برای همین False برگشت داده و تو خط یاده کاربر با ip درست درخواست دانلود داره و میبینید True برگشت داده

این کلیت موضوع بودش حالا بیایم view دانلود و urls بنویسیم

tutorial/urls.py
tutorial/urls.py

فایل urls که چیز خاصی نداره بجز ورودی گرفتن که نوع ورودی uuid مشخص شده و اسم ورودی هم link گذاشتیم . میرسیم به ویومون

auth_system/views.py
auth_system/views.py

خب اینجا ی فانکشن ویو به اسم Download_File داریم که یک ورودی به اسم link میگیره .تو خط اولش اومدیم برسی کردیم ببینیم اصلا همچین لینکی قبلا درست شده یا نه اگه بود که میاد اطلاعاتش تو متغیر temp
میزاره اگرم نبود واسه کاربر صفحه ارور 404 نشون میده .تو خط بعدترش اومدیم ip کلاینتی که درخواست دانلود فایل داده میگیرم با استفاده از تابع get_client_ip که اون از داخل هدر واسمون استخراجش میکنه .

بعدش یک شرط داریم این شرط میگه ببین تاریخ انقضاش گذشته و یا ip برای لینک یکبار مصرف درست شده با ip کلاینتی که الا میخواد دانلود بکنه یکی نبود بیا صفحه 404 نشونش بده

تو دو خط بعدی اومدیم فایل و اسم فایل داخل دوتا متغیر ریختیم. و تو خط بعدی ترش اومدیم فایل تو خروجی صفحه قرار دادیم و خط بعدترش با استفاده از هدر Content-Disposition به اون صفحه اعلام کردیم که یک فایل اینجا پیوست شده به فلان اسم و در اخر اون HttpResponse که ساختیم ریترن کردیم.

نکته : حالا اگه میخواهید کاربر فقط یکبار بتونه از لینک استفاده بکنه خطی که کامنت کردم از کامنتی در بیارید :))

حالا کامل سیستم لینک یکبار مصرفمون درست شدش فقط کافیه این شکلی ازش استفاده کنیم

https://domain.com/download/807b7a2c-a7a0-4a70-85af-fde84063e5ca

تا فایلی که مشخص کردیم بشه دانلود کرد

اینکه چطور روترینگ بکنید و فایل مدیا هارو تو تنظیمات درست بکنید خودتون بهتر میدونید و اگه خوب متوجه نشدید میتونید کامنت بزارید و اگه نیاز بود تو یک ویدیو بصورت واقعی تو پروژه پیاده سازی کنیم این مبحث