تعداد بازدید: 2262

Authorization

سیستم authorization یکی از مکانیزم های امنیتی هر نرم افزاری می باشد که ممکن است در هر نرم افزار به صورت خاص خود نرم افزار پیاده سازی گردد. در لاراول با دو مفهوم Gate , Policy این مکانیزم را پیاده سازی می کنیم.

در راستای authentication ما authorization را داریم. یک شرکت برنامه نویسی رو فرض کنید ، تمامی افراد عضو می تونن از در عمومی وارد شرکت بشن ولی تنها مدیر میتونه وارد اتاق مدیریت بشه. درب ورودی شرکت میشه authentication و ورود به اتاق مدیریت میشه authorization.

هر مدل یه سری عملگر داره (method) که به صورت CRUD (Create , Read , Update , Delete) اون رو می شناسیم.این مکانیزم ها زمانی که به صورت متد در میان ممکنه که نام اون ها تغییر کنه. (create , find , all , update , delete) .

مکانیزم هایی که روی مدل می نشینند هم باید از این عملگر ها پشتیبانی کنند. منظور از این که مکانیزم ها روی مدل می نشینند همان مواردی که در زمان ساختن مدل تحت عنوان option به دستور اضافه می گردد مثل -c که برابر با ساخت Controller می باشد یا آنهایی که مدل را به عنوان option می پذیرند مثل Policy که باید تعریف کرد که برای کدام مدل است (--model).

Authorization از دو سرویس Gate و Policy تشکیل شده است. Gate فارغ از مدل و Policy روی مدل می نشیند.

هر مدل یه سری عملگر داره (CRUD) و به دنبال برخی ماژول هایی که روی مدل می شینه هم اون عملگر های رو داره (controller , policy) پس می شه گفت که policy در کنترلر استفاده میشه و عملگر های مدل (CRUD) رو داره.

AuthServiceProvider

AuthServiceProvider یک کلاس extends شده از ServiceProvider واقع در مسیر App\Providers\AuthServiceProvider می باشد که در آن سرویس authorization فعال سازی می شود.

در درون آن property با نام $policies  وجود دارد که policy ها را در آن باید register کنیم. یعنی بگوییم که ModelPolicy مربوط به مدلی با نام Model می باشد. این متغیر یک آرایه است.

همچنین در متد boot می تونیم Gate ها رو تعریف کنیم و پارامتر های لازم برای اون ها رو بنویسیم. برای تعریف از Gate:define استفاده می کنیم که پارامتر اول نام Gate است و پارامتر دوم cluser مربوطه به همراه ورودی های آن می باشد.

Authorization – Gates

Gate یک امکان اعمال فیلتر روی درخواست های کاربر می باشد که می تواند روی Route ها یا متد های کنترلر اعمال گردد.

در زمان تعریف هر Gate یک نام و یک closure باید برای آن تعریف کنید. نام در زمان فراخوانی استفاده می شود و تابع هم روال اعمال فیلتر رو پیاده سازی می کند. تابع یه سری پارامتر می تونه بگیره که اون پارامتر ها در زمان فراخوانی باید به اون داده بشه.

در مثال زیر ما می خواهیم که قسمتی داشته باشیم برای کاربرانی که subscribe کرده باشند. یعنی فیلدی در جدول users وجود داشته باشد تحت عنوان subscribe که یا 1 باشد یا 0 که به معنی وجود یا عدم وجود اشتراک باشد. در آن طرف هم به ازای درخواست subscribe برای کاربران مشترک برگه ای نمایش دهد و برای کاربران غیر عضو هم پیام خطا.

برای تعریف Gate باید در متد boot در کلاس AuthServiceProvider باید اون رو پیاده سازی کنید. پارامتر های مورد نیاز برای closure رو در این قسمت تعریف می کنیم.

<?php
public function boot()
{
    $this->registerPolicies();
    Gate::define('subscribe',function($user){
        if($user->subscribe)
            return true;
        else
            return false;
    });
}

نکته : می تونیم برای تابع Gate مربوطه از یکی از متد های یک کلاس مثلا policy استفاده کنیم.

بعد از اون مثلا ما در قسمت Route خودمون به ازای endpoint برابر با subscribe یک view را نمایش می دهیم. میخواهیم با استفاده از allows این دسترسی را محدود کنیم برای کاربرانی که subscribe هستند.

<?php
Route::get('/subscribe', function () {
    $user = Auth::user();
    if(Gate::allows('subscribe',$user)){
        return view('subscribe',compact('user'));
    }else{
        return 'You are not subscriber';
    }
})->name('subscribe');

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

همچنین ما می توانیم از  Gate در view استفاده کنیم. یعنی با استفاده از directive برابر با can می تونیم بگیم اگر Gate با نام خاص مجاز بود محتوا رو نمایش بده.

@can('subscribe', Auth::user())
     <li class="nav-item subscribe">
          <a href="{{ route('subscribe') }}" title="subscribe">Subscribe</a>
     </li>
@endcan

نکته : allows یعنی مجاز . عکس اون denies رو داریم که میگه اگر Gate غیر مجاز بود.

Authorization – Policy

امکانی برای اعمال محدودیت بر روی متد های کنترلر می باشد که بر اساس مدل ساخته می شود. بوسیله دستور زیر می تونید یک policy بسازید. مثلا برای مدل با نام Product می تونید policy با نام ProductPolicy انتخاب کنید.

php artisan make:policy ProductPolicy --model=Product

پس از اجرای دستور بالا یک فایل در مسیر app/policies ساخته می شه که در اون یک کلاس با نام ProductPolicy (هم نام با Policy) وجود داره که به صورت پیش فرض دو مدل در اون import شده که یک مدل User است و دیگری مدلی که ما در زمان ساخت policy رو روی اون نشوندیم (مقدار آپشن --model که در این مثال Product می باشد).

<?php

namespace App\Policies;

use App\User;
use App\Product;
use Illuminate\Auth\Access\HandlesAuthorization;

class ProductPolicy
{
    use HandlesAuthorization;

    public function view(User $user, product $product){}

    public function create(User $user){}

    public function update(User $user, product $product){}

    public function delete(User $user, product $product){}
}

این کلاس حاوی یه سری متد است که همون عملگر های گفته شده (CRUD) می باشد. بسته به نیاز به برخی از اون ها یه سری پارامتر داده شده که یکی کاربر جاری سیستم هست و دیگری شئ ساخته شده از مدل Product .

در مثال زیر ما میخواهیم که تنها کاربری قادر به تغییر اطلاعات محصول (Update) باشد که سازنده آن باشد. هر محصول پس از ساخته شدن user_id دارد . پس می توان تشخیص داده که سازنده محصول کیست. برای این کار متد update را به این شکل می سازیم.

<?php
public function update(User $user, product $product)
{
    return $product->user_id === $user->id;
}

بحث بر روی update می باشد. یعنی صفحه ای که در آن فرمی است که بتوان به وسیله آن درخواست update را داد. باید روی این متد policy را روی متد edit اعمال کنیم ، چون تنها راه اعمال درخواست همین است (به دلیل وجود token در فرم نمی توان غیر از این راه درخواست فرستاد).

همان طور که میدانید token یک رشته تصادفی به ازای هر session می باشد. و هکر امکان دارد از هر روشی آن را به دست بیاورد (مثلا از روی یک فرم دیگر). پس برای اطمینان بیشتر باید این Authorize Policy را روی متد update نیز پیاده سازی کنید. یعنی خط کد $this->authorize('update',$product); هم در متد Controller@update و Controller@edit پیاده سازی گردد.

به ProductController می رم و روی متدی که ویرایش محصول را نمایش می دهد این authorize را پیاده سازی می کنم. این متد مربوط به کنترلر جاری می باشد پس برای فراخوانی آن از this->authorize استفاده می کنیم. ورودی اول نام Policy@method می باشد و ورودی های بعد پارامتر های متد مربوطه از Policy می باشد.

<?php
    public function edit($id)
    {
        $product = products::findOrFail($id);
        $this->authorize('update',$product);
        $categories = category::all();
        $title = "edit $product->name";
        return view('edit-product',compact('product','categories','title'));
    }

با اجرای کد بالا درخواست به ازای مجاز بودن به صفحه مربوطه میره و در غیر اینصورت به 403 ریدایرکت میشه. دقت داشته باشید شئ $product برای policy مربوطه فرستاده شده.

policy ها در view هم بوسیله can قابل استفاده هستند. فراخوانی به ازای نام و پارامتر های مورد نیاز میسر می باشد.

@can('update', $product)
     <a type="button" class="btn btn-info edit" href="{{ route('edit.product', ['id'=>$product->id]) }}">Edit</a>
@else
     No edit
@endcan

تفاوت های Gate و Policy

Gate و Policy سرویس های مربوط برای پیاده سازی Authorization در لاراول می باشد که محدودیتی در استفاده از آن نداریم ، یعنی در نرم افزار خود می توان با توجه به نیاز خود از هر دوی آن ها استفاده کرد. با این وجود تفاوت هایی را با هم دارند :

  • Policy روی مدل میشینه ولی Gate به مدل خاصی مرتبط نیست کما این که می تونه در Route هم فراخوانی بشه و یا متدی از یک controller .
  • Gate یک جنبه authorize عمومی داره اما Policy میشه گفت که یک پک به ازای مدل خاص و بر اساس عملیات CRUD می باشد.
  • پارامتر ها در Policy در متدهای کلاسی که بر اساس مدل خاص ساخته شده موجود به صورت پیش فرض موجوده ضمن این که کاربر جاری رو $user هم به برخی متد ها میده اما در Gate باید تمامی پارامتر ها رو دلخواه و بر اساس نیاز تعریف کنیم.
  • Gate یک closure هست و Policy یک کلاس با متد های مختلف . اگر چند Gate با اهداف مشخص روی یک مدل تعریف شود می شود policy.

در پایان می توان گفت که محدودیت های موجود در لاراول به سه قسم است :

  • Authentication یا سیستم عضویت که کاربران guest و users را از هم جدا می کند.
  • Gates یکی از روش های پیاده سازی سرویس Authorization.
  • Policy که روی مدل می نشیند و روش دیگری از سرویس Authorization می باشد.

اشتراک گذاری :

مدیر وب سایت گنوتک . برنامه نویسی رو با زبان C در هفده سالگی شروع کردم . در حال حاضر به برنامه نویسی php برپایه معماری MVC , HMVC و همچنین سیستم مدیریت محتوای WordPress و فریم ورک محبوب لاراول علاقه مند هستم و دوست دارم اطلاعاتم رو با شما به اشتراک بگذارم.

۰ دیدگاه برای Authorization

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *