آموزش Mass Assignment در لاراول

دسته بندی: برنامه نویسی
سطح مقاله: متوسط
زمان مطالعه: 8 دقیقه
۳۰ خرداد ۱۳۹۸

در زمان کار با model ها و دیتابیس در لاراول، Mass Assignment عبارتی است که زیاد به گوشتان می خورد. اما این عبارت به چه معنا است؟ چرا Mass Assignment می تواند در مواردی امنیت وب سایت لاراولی شما را در معرض خط قرار دهد؟ و چگونه می توان از این خطرات جلوگیری کرد؟ این ها همه مواردی است که آن ها را در این مقاله مورد بررسی قرار می دهیم. در پایان این مقاله شما می توانید به راحتی از طریق Mass Assignment عملیات دیتابیسی خود را در لاراول پوشش دهید. و البته این کار را همراه با تعمین امنیت برنامه لاراولی خود انجام دهید.

آموزش Mass Assignment

Mass Assignment چیست

­­­در لاراول برای ایجاد رکورد یا ویرایش آن دو راه وجود دارد. در روش اول می توانیم اتریبیوت های (Attribute) یک رکورد را دانه به دانه وارد کرده و سپس آن ها را از طریق متدها الوکوئنت save() و update() ذخیره کنیم. برای فهمیدن بیشتر این موضوع به مثال زیر توجه کنید:

public function store(Request $request) {
    $post = new Post();
    $post->title = $request->input('title');
    $post->description = $request->input('description');
    $post->body = $request->input('body');
    $post->status = $request->input('status');
    $post->save();
    return redirect()->back();
}

 در این مثال برای ساخت یک رکورد جدید در جدول posts اتریبیوت های آبجکت $post را با استفاده از اطلاعات فرمی که به کنترلر ارسال شده یکی یکی پر کردیم. در واقع $post یک آبجکت مدل (Object model) از جدول posts است. در پایان برای ذخیره اطلاعات و ساخته شدن نهایی رکورد جدید از متد save() استفاده کردیم. اما تصور کنید که جدول شما دارای 20 ستون باشد. پس مجبوریم برای ساخت رکورد های جدید با این روش به اندازه یک تومار کد بزنیم!

برای جلوگیری از این موضوع و راحتی کار از روش Mass Assignment استفاده می کنیم. در این روش دوم، مقادیر تمام اتریبیوت ها را به یکباره وارد کرده و می توانیم کد بالا را در یک خط کد ساده خلاصه کنیم! به مثال زیر دقت کنید:

public function store(Request $request) {
    Post::create($request->all());
    return redirect()->back();
}

 در مثال بالا برای راحتی بیشتر تمام مقادیر فرم را در قالب ریکوئستی که به کنترلر ارسال شده به متد create() ارسال کردیم. همه چیز عالی به نظر می رسد. اما باید بدانید که Mass Assignment بدون تمهیدات امنیتی یک تهدید بزرگ امنیتی است. اما چرا؟

تصور کنید شما جدولی از کاربران با نام users و با اتریبیوت های زیر دارید:

  • id
  • firstname
  • lastname
  • age
  • role

اتریبیوت role همان سمت یا رتبه کاربر است که دسترسی های کاربر در سایت از طریق آن معین می شود. همانطور که حدس می زنید کاربران عادی نباید به این اتریبیوت دسترسی داشته و بتوانند آن را تغییر دهند. چرا که در این صورت ممکن است یک کاربر عادی با خواست و اراده خودش ناگهان به مدیر سایت تبدیل شود! اما چگونه با روش Mass Assignment این اتفاق خواهد افتاد؟

احتمالا شما با خیال راحت فیلد role را در فرم ویرایش اطلاعات کاربری در پروفایل آن ها در نظر نمی گیرید. اما کاربر با ارسال یک درخواست غیر مجاز فیلد جدیدی با نام role را به همراه سایر اطلاعات خود به کنترلر ارسال می کند. مقدار جدید role به صورت زیر در متد update() لحاظ می شود:

public function update(Request $request , User $User) {
    $User->update($request->all());
    return redirect()->back();
}

 تبریک می گوییم! حالا شما یک کاربر مدیر جدید دارید که خیالات شومی در سر دارد! اما راهکار جلوگیری از این خطر چیست؟ برای دفع این خطر دو راه وجود دارد. توجه کنید که هر دوی این راه ها در مدل مربوط به هر موجودیت انجام می گیرد. مثلا در مورد جدول posts شما باید هر کدام از این راه ها را در مدل Post پیاده کنید. در ادامه هر کدام از این راه ها را بررسی خواهیم کرد.

Fillable چیست؟

استفاده از روش Fillable به لاراول می گوید که کدام یک از اتریبیوت های هر جدول می توانند Mass Assign شوند. در این روش شما یک متغیر آرایه ای از نوع protected با نام $fillable در مدل مربوط به جدول تعیین می کنید. در واقع این آرایه یک لیست سفید برای Mass Assign کردن جدول مربوطه است. مثال زیر یک نمونه از Fillable را برای جدول کاربران نشان می دهد:

namespace App;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $fillable = ['firstname' , 'lastname' , 'age'];
}

 در این مثال از این بعد فقط اتریبیوت های lastname ،firstname و age می توانند Mass Assign شوند و در صورت Mass Assign کردن اتریبیوت های دیگر یعنی id و role کاربر با خطا مواجه می شود.

Guarded چیست؟

در روش guarded به لاراول اطلاع می دهیم که به چه اتریبیوت هایی اجازه Mass Assign شدن ندهد. در واقع روش Guarded دقیقا برعکس روش Fillable عمل می کند. برای تعریف Guarded مانند Fillable کافی است یک متغیر آرایه ای از نوع protected و با نام $guarded در مدل مربوط به جدول تعریف کنیم. مثلا در کد زیر روش Guarded را برای جدول کاربران در مدل User تعریف کرده ایم:

namespace App;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $guarded = ['id' , 'role'];
}

 در این مثال از این پس هیچ کاربری اجازه Mass Assign کردن اتریبیوت های id و role را ندارد. اما هر اتریبیوتی به غیر از این دو می توانند به راحتی Mass Assign شوند.

بین Fillable یا Guarded کدام را انتخاب کنیم؟

اگر می خواهید همه مسائل امنیتی را رعایت کنید باید بگوییم که در هر صورت استفاده از متغیر $fillable بیشتر به نفع شما است! چرا که در مورد روش Guarded ممکن است فیلدهای اضافه دیگری به غیر از فیلدهای جدول مورد نظرمان به همراه Request ارسال شوند. اگر از Guarded استفاده کرده باشیم کاربر به خطای دیتابیس برخورد خواهد کرد چرا که لاراول تلاش می کند اطلاعات را درون ستون هایی بریزد که وجود ندارند! اما در صورت استفاده از $fillable برنامه با Exception مواجه می شود که امن است.

اما به هر حال رسم بر این است که هر زمان شما جدولی با ستون های زیاد داشتید و می خواستید فقط چند ستون آن را از Mass Assignment محافظت کنید از روش Guarded استفاده کنید. برعکس، اگر جدولی داشتید که نیاز است بیشتر ستون های آن از Mass Assignment مصون بمانند از روش Fillable استفاده کنید.

جمع بندی

در صورت نخواندن این مقاله با یک خطر بزرگ مواجه هستید! در این مطلب روش Mass Assignment را معرفی و خطرات استفاده از آن را تشریح کردیم. برای جلوگیری از خطر امنیتی روش Mass Assignment دو را وجود دارد: استفاده از لیست سفید و لیست سیاه برای اتریبیوت های جدول. همینطور دیدیم که برای انتخاب بین روش اول و دوم چه معیارهایی باید بررسی شده و در نظر گرفته شوند. در صورتی که در مورد این مقاله هر گونه سوال یا مشکلی داشتید از پاسخگویی به سوالات شما خوشحال می شویم!

اگر می خواهید بیشتر در مورد لاراول مطالعه کنید مقالات زیر را دنبال کنید

 

چه امتیازی به این مقاله می دید؟
نویسنده

نظرات کاربران

Ali_Mousavi

سلام،در حال حاضر دارم php یاد میگیرم…اما همیشه از اینده این زبان برنامه نویسی میترسم (با وجود وردپرس،wix,webflow,…)و نتیجه خیلی از بحث های اینترنتی اینه که php به درد نمیخوره و در حال افوله(به دلیل وجود وبسایت سازهایی که ذکر کردم)…
خواستم بدونم امیدی هست برای یادگیری php ؟واینکه بازار کارش برا اینده چطوره ؟؟؟لطفا راهنمایی کنین …خیلی گیج شدم …

امین

سلام
ممنون از مقاله مفیدتون
فقط یه سوال
Mass Assignment زمانی میتونیم استفاده کنیم که اتریبوت name در فرم هامون == باشه با اسم ستون ها در دیتابیس درسته؟
یعنی مثلا اگر در فرم آدرس کاربر رو با اینپوتی که name ش name=”address” باشه باید در دیتابیس هم ستونی به نام address داشته باشیم در Mass Assignment در غیر اینصورت با خطا مواجه میشیم درسته؟ خب حالا اگر در صورتی که فرممون تعداد فیلدای زیادی داشته باشه و بخوایم امنیت دیتابیسمون بیشتر بشه و مقدار name فیلد ها متفاوت با نام ستونشون در دیتابیس باشه آیا راهی هست که بشه از روش Mass Assignment استفاده کرد؟
ممنونم

امین

سلام
ممنون از مقاله مفیدتون
فقط یه سوال
Mass Assignment زمانی میتونیم استفاده کنیم که اتریبوت name در فرم هامون == باشه با اسم ستون ها در دیتابیس درسته؟
یعنی مثلا اگر در فرم آدرس کاربر رو با اینپوتی که name ش name=”address” باشه باید در دیتابیس هم ستونی به نام address داشته باشیم در Mass Assignment در غیر اینصورت با خطا مواجه میشیم درسته؟ خب حالا اگر در صورتی که فرممون تعداد فیلدای زیادی داشته باشه و بخوایم امنیت دیتابیسمون بیشتر بشه و مقدار name فیلد ها متفاوت با نام ستونشون در دیتابیس باشه آیا راهی هست که بشه از روش Mass Assignment استفاده کرد؟
ممنونم

ارسال دیدگاه
خوشحال میشیم دیدگاه و یا تجربیات خودتون رو با ما در میون بذارید :

 
گزارش مشکل