آموزش احراز هویت با API در لاراول

دسته بندی: لاراول
زمان مطالعه: 13 دقیقه
۲۴ تیر ۱۳۹۹

زمانی که در حال توسعه یک API با لاراول هستید،‌ یکی از قسمت‌های مهم احراز هویت (Authentication) است. احراز هویت در API به طور خلاصه باید به صورتی توسعه داده شود، که در زمان درخواست از سمت Client به Server، یک مشخصه برای سرور ارسال شود، تا بتواند تشخیص دهد، که آیا کاربر مورد نظر احراز شده است، یا خیر که بتواند، جوابی را به Client ارسال کند. در این مقاله به بررسی احراز هویت با API در لاراول می‌پردازیم.

فهرست محتوای این مقاله

پکیج Sanctum

لاراول در نسخه جدید خود پکیجی به نام Sanctum را منتشر کرد. هدف این پکیج استفاده از راهی مناسب برای احراز هویت در نرم افزارهایی، به نام SPA یا ‌Single Page Application، است. که از طریق فریم ورک‌های جاوا اسکریپت توسعه داده می‌شوند.برای احراز هویت با API در لاراول، کار Sanctum در اینجا به پایان نمی‌رسد، و این پکیج را در تمامی اپلیکیشن‌ها و سیستم‌های Token Base می‌توان استفاده کرد.

این پکیج همچنین قابلیت ساختن چند Token را برای هر کاربر در اپلیکیشن شما دارد، که حتی می‌توانید برای هر توکن چندین قابلیت (Ability) قرار دهید، و از هر توکن به منظور دسترسی به قسمت خاصی از سیستم خود استفاده کنید. به زبان ساده‌تر به هر توکن می‌توانید دسترسی‌هایی در سیستم خود دهید، که در ادامه بیشتر در مورد آن صحبت خواهیم کرد.

نصب پکیج Sanctum

برای نصب پکیج Sanctum از طریق خط فرمان دستور زیر را در پروژه خود اجرا کنید.

composer require laravel/sanctum

بعد از نصب پکیج با وارد کردن دستور زیر فایل‌های پکیج را به پروژه خود منتقل کنید.

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

با اجرای دستور بالا فایل‌های پکیج از جمله، فایل sanctum.php در مسیر config، که تنظیمات کلی پکیج پروژه‌ی شما در آن قرار دارد و همچنین فایل‌های ‌Migration مربوط به جداول، در پروژه شما قرار داده می‌شود.

بعد از اجرای دستور بالا نیاز است، در اولین مرحله جداول مربوط به Sanctum را به دیتابیس خود اضافه کنیم. دستور زیر را در خط فرمان پروژه خود اجرا کنید.

php artisan migrate

جدولی که از طریق کد بالا ساخته می‌شود، در فایل migration مربوط به sanctum در مسیر database/migrations و با نام personal_access_tokens قرار دارد.

در صورتی که می‌خواهید، فایل‌های مربوط به دیتابیس اجرا نشود، در فایل ‌AppServiceProvider.php متد Sanctum::ignoreMigrations را در متد register صدا بزنید.

تنظیمات ‌Sanctum

در فایل config/sanctum.php تنظیمات کلی مربوط به پکیج Sanctum وجود دارد، که در زیر به شما توضیح خواهیم داد.

  • stateful: اینجا می‌توانید دامنه‌هایی که اجازه درخواست به سرور را دارند، تعریف کنید.
  • expiration: مربوط به انقضای توکن است، که بر حسب دقیقه محاسبه می‌شود، و زمانی که null قرار بگیرد، توکن منقضی نخواهد شد.
  • middleware: زمانی که از احراز هویت در نرم افزار SPA استفاده می‌کنید، باید csrf-token هایی که از طریق پکیج Sanctum به نرم افزار داده ‌می‌شود، اعتبار سنجی شوند. می‌توانید ‌Middleware‌های مربوط به این کار را اینجا قرار دهید.

استفاده از پکیج Sanctum در پروژه

می‌خواهیم در پروژه‌ی خودمان از طریق پکیج Sanctum یک API بنویسیم، که کاربر را از طریق توکن احراز هویت می‌کند، و بعد از ورود کاربر یک توکن به آن می‌دهد، و در درخواست‌های بعدی با قرار دادن آن توکن در Header درخواست به سرور می‌گوییم، که درخواست از طریق کدام کاربر به سرور ارسال شده است.

در اولین مرحله یک پروژه جدید لاراول با دستور زیر بسازید.

composer create-project --prefer-dist laravel/laravel ApiAuthenticateSystem

بعد از انجام مراحل Config پروژه و نصب پکیج Sanctum که در بالا توضیح دادیم، یک مدل User تعریف می‌کنیم ( که لاراول به طور پیش‌فرض، مدل ‌User را دارد. )

برای تولید توکن توسط Sanctum باید از Trait به نام HasTokenApi در مدل خود استفاده کنیم، تا متدهای ایجاد و بررسی توکن برای مدل مربوطه، به مدل اضافه شود.

در مدل User کد زیر را قرار دهید.

<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password','username'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

در قسمت اول تعریف کلاس User از Trait مربوط به پکیج Sanctum با نام HasApiTokens استفاده کردیم، که همچنین در قسمت اول فایل آن را وارد (Import) کردیم.

ورود با Api

یک متد برای ورود و دریافت توکن از طریق Api می‌خواهیم بسازیم. به این منظور یک Controller ایجاد می‌کنیم. با استفاده از دستور زیر می‌توانید یک Controller ایجاد کنید.

php artisan make:controller Auth/UserController

با اجرای دستور بالا یک Controller در مسیر app/Http/Controller/Auth ساخته می‌شود.

حال باید متد login را به صورت زیر بنویسیم.

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Illuminate\Support\Facades\Hash;

class UserController extends Controller
{
    public function login()
    {
        \request()->validate([
            'email' => 'required|email',
            'password' => 'required'
        ]);

        $user = User::where('email', \request('email'))->first();

        if (! $user || ! Hash::check(\request('password'), $user->password)) {
            throw ValidationException::withMessages([
                'email' => ['The provided credentials are incorrect.'],
            ]);
        }

        return $user->createToken('token_base_name')->plainTextToken;
    }
}

در متد لاگین از طریق ایمیل و رمزعبور اول صحت اطلاعات وارد شده را بررسی می‌کنیم و در صورت صحیح بودن اطلاعات از طریق متد createToken یک توکن برای کاربر مورد نظر در دیتابیس ایجاد می‌کنیم و توکن خام را به کاربر نشان می‌دهیم.

حال باید یک ‌مسیر برای ورود در فایل routes/api.php به شکل زیر ایجاد می‌کنیم.

Route::post('/login', 'Auth\[email protected]');

مسیر بالا را به متد login در فایل UserController.php مرتبط کردیم و زمانی که آدرس localhost:8000/api/login را وارد کنید به متد مربوطه متصل خواهد شد.

زمان درخواست مسیر بالا با متد POST باید در body درخواست دو پارامتر با نام email و password قرار دهیم، که اطلاعات ما خواهند بود. خروجی در نرم افزار Postman به صورت زیر است.

احراز هویت با API در لاراول

خروجی را برای درخواست‌های بعد باید در ‌Header درخواست خود، وارد کنید.

محافظت از مسیر ها

می‌خواهیم از طریق پکیج Sanctum از مسیرها محافظت کنیم، و یک مسیری بسازیم، که فقط در زمانی که کاربر وارد شده بود، و درخواست دارای توکن بود آن مسیر اجرا شود.

برای انجام این کار باید یک guard با درایور token ایجاد کنیم، و ما guard پیش‌فرض api را تغییر می‌دهیم.

در فایل config/auth.php قسمت guards را به صورت زیر تغییر می‌دهیم. توجه کنید به صورت پیش‌فرض نیز لاراول درایور api را token قرار داده است. در غیر این صورت، به صورت زیر تغییر دهید.

'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins'
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],
    ],

تنظیمات بالا مربوط به پروژه آموزش احراز هویت در لاراول است.

حال در فایل routes/api.php یک مسیر به صورت زیر ایجاد می‌کنیم.

Route::get('/user', function (){
    return \request()->user();
})->middleware('auth:sanctum');

مسیر بالا اطلاعات کاربری که به توکن ارسالی در Header، مرتبط است را برمی‌گرداند.

در Postman به صورت زیر باید در تب Auth نوع احراز هویت را Bearer انتخاب کنید، و در فیلد بعدی توکن را به صورت زیر وارد کنید.

احراز هویت با API در لاراول

در صورتی که توکن را وارد نکنید با خطای 401 (Unautheticated) برمی‌خورید. و در صورت وارد کردن اطلاعات به شما نمایش داده می‌شود.

برای اضافه کردن توکن در ‌Header درخواست، در فریم ورک‌های جاوا اسکریپت یا اجرای درخواست بدون استفاده از Postman باید توکن را با کلید Authorization و به صورت {Bearer {token در Header قرار دهید.

مسیر Logout

زمانی که قرار است از نرم افزار خارج شوید باید عملیات Logout را انجام دهید و در این میان نیاز است توکن ساخته شده را حذف (Revoke) کنید.

مسیر Logout را به صورت زیر در فایل routes/api.php قرار دهید.

Route::get('/user/logout', function (){
    \request()->user()->tokens()->delete();
    return response([], 204);
})->middleware('auth:sanctum');

در ارسال درخواست به آدرس بالا نیز باید توکن را بفرستید، زیرا که نیاز است کاربر وارد شده را پیدا کند، و با متد tokens تمامی توکن‌های آن را بگیرد، و بعد از آن با delete تمامی توکن‌های مربوط به کاربر وارد شده را حذف می‌کند.

دقت کنید که در کد بالا تمامی توکن‌های کاربر حذف می‌شود، ولی از طریق کد زیر می‌توانید توکن مربوطه را پیدا کنید، و فقط آن را حذف کنید.

request()->user()->tokens()->where('id', $id)->delete();

متغیر id همان id مربوط به توکن خواهد بود که می‌توانید از راه‌های مختلف آن را به دست آورید.

دسترسی‌ها در Sanctum

پکیج Sanctum یک ویژگی با نام Ability دارد، که می‌توانید در هنگام ایجاد توکن در قسمت ورود برای هر توکن که ایجاد می‌کنید، یک سری Ability نیز به آن دهید. در این مقاله یک روش نیز برای دسترسی به قسمت‌های مختلف پروژه از طریق قابلیتی به نام Policy در لاراول را به شما خواهیم گفت.

ایجاد Ability برای کاربر

در فایل UserController.php که در بالاتر ایجاد کردیم، متد login را به صورت زیر تغییر دهید.

public function login()
    {
        $this->validate(\request(),[
            'email' => 'required|email',
            'password' => 'required'
        ]);

        $user = User::where('email', \request('email'))->first();

        if (! $user || ! Hash::check((int)\request('password'), $user->password)) {
            throw ValidationException::withMessages([
                'email' => ['The provided credentials are incorrect.'],
            ]);
        }
        
        return $user->createToken('token_base_name', ['user:view'])->plainTextToken;
    }

در کد بالا در ورودی دوم متد createToken یک آرایه قرار می‌گیرد، که شامل قابلیت‌هایی (Ability) است، که توکن می‌تواند آن را انجام دهد. ما یک آرایه با یک خانه به صورت user:view به آن دادیم، که کاربر در صورت ورود می‌تواند، در قسمتی از نرم افزار که نیاز به این دسترسی دارد، دسترسی داشته باشد.

ایجاد قوانین دسترسی

می‌توانیم از قابلیت Policy در لاراول استفاده کنیم. Policy در لاراول به ما این امکان را می‌دهد، تا برای دسترسی به مدل‌های خود یک قاعده و قانون بنویسیم.

برای مثال می‌خواهیم در یک Controller پنج قسمت لیست، نمایش، اضافه، ویرایش و حذف را برای یک مدل بنویسیم. می‌توانیم برای آن مدل ‌یک Policy تعریف کنیم، تا برای هر کدام از عملیات بالا یک قانون بنویسیم.

برای ایجاد یک Policy از طریق خط فرمان دستور زیر را اجرا کنید.

php artisan make:policy UserPolicy -m User

کلید m- یک مدل را انتخاب می‌کند.

فایل Policy در مسیر app/Http/Policies قرار می‌گیرد. فایل UserPolicy را باز کنید.

متد‌های مختلفی در آن تعریف شده است، که همچنین شما ‌می‌توانید، متد سفارشی خود را نیز بنویسید.

ما در این پروژه می‌خواهیم، برای نمایش اطلاعات کاربر این روش را بررسی کنیم.

متد view مربوط به نمایش یک کاربر می‌باشد. دو ورودی می‌گیرد، که اولی مربوط به کاربر وارد شده است، و دومی مربوط به مدلی است، که قرار است عملیاتی بر روی آن اجرا شود.

متد view را به صورت زیر تغییر دهید.

public function view(User $user, User $model)
    {
        return $user->tokenCan('user:view') && $user->id === $model->id;
    }

دو شرط قرار داده‌ایم. یکی اینکه کاربر وارد شده دسترسی user:view را داشته باشد، و دوم اینکه مدلی که درخواست می‌کند دقیقا همان مدل خودش باشد، و نتواند اطلاعات دیگر کاربران را مشاهده کند.

تا اینجا ما قانون مربوط به نمایش اطلاعات کاربر را نوشته‌ایم. حال در فایل UserController.php که در قسمت اول آموزش ساخته‌ایم، یک متد با نام getUser به صورت زیر می‌نویسیم.

public function getUser()
    {

        $this->authorize('view', \request()->user());

        return \request()->user();
    }

در قسمت اول با استفاده از متد authorize برقرار بودن قانون مربوط به مدل درخواستی که همان مدل کاربر وارد شده است، را بررسی می‌کنیم. ورودی اول این متد، همان متدهای مربوط در فایل policy است، و ورودی دوم، مدل درخواستی که قصد انجام عملیاتی (در اینجا نمایش) بر روی آن را داریم، است.

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

Route::get('/user','Auth\[email protected]')->middleware('auth:sanctum');

حال اگر دوباره یک توکن جدید بگیریم، و به آدرس localhost:8000/api/user به همراه توکن درخواست بزنیم، اطلاعات به ما نمایش داده می‌شود. ولی اگر توکن ما اجازه دسترسی به آن قسمت را نداشته باشد، (طبق قانون نوشته شده در Policy نباشد) با خطای عدم دسترسی 403 مواجه می‌شوید.

جمع‌بندی:

در این مقاله نحوه‌ی پیاده‌سازی احراز هویت با API در لاراول از طریق پکیج Sanctum که توسط خود لاراول توسعه داده شده است، را مورد بررسی قرار داده‌ایم. این پکیج به صورت Token Base کار می‌کند. به این معنی که یک توکن به شما می‌دهد. و در درخواست‌های بعدی که نیاز به احراز هویت دارد، آن توکن را باید در Header درخواست خود وارد کنیم. همچنین ویژگی Ability در پکیج را توضیح دادیم. و با یک مثال نشان دادیم، که چطور می‌توانید یک سیستم دسترسی در پروژه خود ایجاد کنید.

اگر به یادگیری بیشتر لاراول علاقه داری می‌توانی در دوره آموزشی لاراول کاربردی (بسته پروژه محور) شرکت کنی، این دوره شامل ۱۲ پروژه کاربردی و پر استفاده در دنیای واقعی است، که تمامی پروژه‌ها به صورت کامل برنامه‌ نویسی خواهند شد، تا دانشجو بتواند با روند ایجاد و تکمیل پروژه به صورت کامل آشنا شود.

چه امتیازی به این مقاله می دید؟
نویسنده وحید حسنی
از دوست داران دنیای تکنولوژی مخصوصا دنیای وب از توسعه دهندگان وب مخصوصا بک اند از عاشقان پی اچ پی مخصوصا لاراول از دیوانگان کار کردن مخصوصا در آی ویرا ;-)

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

اولین دیدگاه این پست رو تو بنویس !

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