درود دوستان! یکی از ویژگی‌های پرکاربرد لاراول Signed URL ها هست. این ویژگی برای اضافه کردن یک لایه امنیتی بیشتر به آدرس‌هایی که بصورت عمومی در دسترس هستن استفاده میشه.

فرض کنیم یک سرویس خبرنامه ایمیلی داریم و می‌خوایم برای کاربرانی که مایل به دریافت خبرنامه نیستن یک لینک لغو اشتراک بسازیم. برای مثال لینک لغو عضویت برای کاربر شماره ۹۰ می‌‌تونه به صورت زیر باشه:

http://example.com/unsubscribe/90

وقتی این کاربر روی این لینک کلیک می‌کنه دیگه هیچ ایمیلی دریافت نخواهد کرد. حالا تصور کنین یک شخص که به این لینک دسترسی داره، اون رو دستکاری می‌کنه و بجای ۹۰، از شماره ۸۰ استفاده می‌کنه. در صورت عضویت ایمیل کاربر شماره ۸۰ هم لغو میشه! و به این صورت می‌تونه برای بقیه کاربرا هم این عملیات رو انجام بده.

یه راه حل می‌تونه فعال کردن احراز هویت برای این لینک باشه. اما معمولاً لغو خبرنامه‌های ایمیلی بدون نیاز به احراز هویت انجام میشه و یا چون توسط سرویس‌های شخص ثالث و مجزا ارسال میشن، احراز هویت کاربردی نداره. اینجاست که Signed URL های لاراول به کار ما میان 👌

 

ساختن یک Signed URL

ابتدا فرض کنیم یک Named Route داریم مثل زیر:

Route::get('unsubscribe/{user_id}', '...')->name('unsubscribe');

 برای ساختن یک Signed URL برای این روت از متد signedRoute از کلاس URL استفاده می‌کنیم:

use Illuminate\Support\Facades\URL;

$url = URL::signedRoute('unsubscribe', ['user_id' => 429]);

به همین سادگی! آدرسی که تولید میشه به شکل زیر خواهد بود:

http://example.com/unsubscribe/429?signature=897fa0b2832a1ebf57726ae80576f9b900dba98dbc7cc670a85d0d83a0297dcf

همونطور که می‌بینیم یک پارامتر به اسم signature به آخر این آدرس اضافه شده که اختصاصی برای این آدرس هست. اگه یکی از خصوصیت‌های آدرس (مثلاً user_id) عوض بشه، این آدرس نامعتبر و ادامه فرآیند متوقف میشه.

 

اعتبارسنجی آدرس‌های Signed

ابتدا میدلور زیر رو به قسمت $routeMiddleware فایل app/Http/Kernel.php اضافه کنیم:

protected $routeMiddleware = [
    // ...
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
];

مرحله بعد اینه که این میدلور رو به روت مورد نظرمون نسبت بدیم:

Route::get('unsubscribe/{user_id}', '...')->name('unsubscribe')->middleware('signed');

از حالا به بعد، این روت زمانی به درستی کار می‌کنه که پارامتر signature با مقدار معتبر وجود داشته باشه. اگه signature نامعتبر باشه، چنین خطایی می‌گیریم:

 

Signed URL های موقت

می‌تونیم آدرس‌هایی تولید کنیم که بعد از مدت زمانی مشخصی باطل میشن. برای این کار، توی پارامتر سوم متد signedRoute مشخص می‌کنیم که تا چه زمانی این آدرس معتبر هست:

$url = URL::signedRoute(
    'unsubscribe', ['user_id' => 429], now()->addMinutes(30)
);

اینجا آدرسی که تولید میشه تا ۳۰ دقیقه معتبر خواهد بود. البته یک متد اختصاصی هم به اسم temporarySignedRoute برای این کار وجود داره که تفاوت چندانی با کاری که انجام دادیم نداره و فقط موقعیت آرگومان‌ها تغییر پیدا می‌کنه:

$url = URL::temporarySignedRoute(
    'unsubscribe', now()->addMinutes(30), ['user' => 429]
);

 

خب دوستان این هم از این آموزش و امیدوارم استفاده کرده باشد. روزتون خوش 😉✌️