تخفیف ویژه

آموزش استفاده از پکیج passport در لاراول

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

مبحث Restful Api، همواره یکی از مباحث مورد علاقه‌ی توسعه‌ دهندگان فریم‌ورک‌های مدرن جاوا اسکریپت و هم‌چنین اپلیکیشن‌های موبایل بوده است. Rest مخفف Representational State Transfer و در واقع، یک معماری برای تبادل اطلاعات از طریق شبکه و به‌ وسیله‌ی وب‌سرویس است که اولین بار توسط Roy Fielding در سال 2000 میلادی معرفی شد. اصطلاح Restful هم به طور خلاصه، به وب‌سرویس‌هایی که از این معماری استفاده می‌کنند، اطلاق می‌شود.

پکیج Passport در لاراول یکی از پکیج‌های رسمی لاراول است که اعتبارسنجی وب‌سرویس‌ها را با استفاده از معماری Rest، برای توسعه‌دهندگان لاراول آسان می‌کند. این پکیج با استفاده از پروتکل OAuth2 و همین‌طور  الگوریتم JWT، ایجاد توکن‌های دسترسی شخصی یا Personal Access Token‌ها را برای اعتبارسنجی کاربران لاگین شده ممکن می‌سازد. این توکن منحصربه‌فرد، با هر درخواست کاربر، به سمت سرور ارسال می‌شود و دسترسی به مسیرهای حفاظت شده را برای کاربر ممکن می‌سازد.

در این مقاله، قصد داریم تا شما را به طور عملی، با نحوه‌ی ایجاد توکن‌های دسترسی شخصی و نحوه‌ی ذخیره‌سازی و استفاده از آن به وسیله‌ی پکیج Passport در لاراول آشنا کنیم؛ تا بتوانید اعتبارسنجی وب سرویس‌های اپلیکیشن خود را به آسان‌ترین شکل، با استفاده از ویژگی‌های جذاب این پکیج انجام دهید. پس تا انتهای این مقاله با آموزش استفاده از پکیج Passport در لاراول، با ما همراه باشید .

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

نیازمندی‌های اولیه

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

نصب لاراول

به پوشه‌ی دلخواه خود بروید و دستور زیر را برای نصب لاراول اجرا کنید:

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

با دستور زیر می‌توانید پروژه را اجرا کنید:

php artisan serve

پس از اجرای این دستور، پروژه بر روی پورت 8000 لوکال هاست در دسترس است. با وارد کردن آدرس http://localhost:8000 در نوار آدرس مرورگر، با این صفحه مواجه می‌شوید.

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

راه‌اندازی دیتابیس

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

DB_DATABASE=passport
DB_USERNAME=root
DB_PASSWORD=

اکنون دیتابیس آماده است. در قدم بعدی باید پس از نصب پکیج، جداول موردنظر خود را ایجاد کنیم.

نصب و راه‌اندازی پکیج

با اجرای دستور زیر در مسیر پروژه، پکیج Passport را نصب کنید:

composer require laravel/passport

ایجاد جداول

پس از آن که نصب پکیج به پایان رسید، با اجرای دستور زیر، جداولی که برای کار با Passport در لاراول نیاز است، به منظور ذخیره‌ی توکن‌ها، کلاینت‌ها و... را ایجاد کنید. فایل Migration مربوط به این جداول، در محتوای پکیج، موجود در پوشه‌ی vendor قرار گرفته‌اند.

Php artisan migrate

ایجاد کلیدهای رمزنگاری

پس از اجرای دستور فوق، به منظور ایجاد کلیدهای رمزنگاری توکن‌ها، دستور زیر را اجرا کنید.

 php artisan passport:install

HasApiTokens

سپس به فایل User.php در مسیر app/Models مراجعه کرده و Trait با نام HasApiTokens را به مدل مربوطه اضافه کنید.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
    use HasFactory, Notifiable, HasApiTokens;

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

    /**
     * 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',
    ];
}

یکی از فواید افزودن این Trait به مدل User، دسترسی مدل به تعدادی متد کمکی است که می‌توان با استفاده از این متدها کارهایی نظیر ایجاد توکن، دسترسی به توکن ایجاد شده برای کاربر، بررسی Scope توکن‌ها و... انجام داد. در ادامه از این متدهای کمکی استفاده خواهیم کرد.

ایجاد مسیرها

اکنون باید متد ()boot در فایل AuthServiceProvider را به شکل زیر بروز کنیم:

<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        // 'App\Models\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Passport::routes();
    }
}

افزودن خط فوق به متد ()boot، مسیرهای مورد نیاز برای ایجاد و لغو توکن‌ها را به اپلیکیشن اضافه می‌کند.

Api Guard

اکنون نوبت آن رسیده که با استفاده از TokenGuard در Passport، درخواست‌های Api ورودی را احراز هویت کنیم. با مراجعه به فایل auth.php در پوشه‌ی config، درایور مربوط به Guard با نام api را به شکل زیر، برابر با مقدار passport قرار دهید.

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

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

تغییر تاریخ انقضای توکن

تاریخ انقضای توکن‌ها در پکیج Passport در لاراول، به صورت پیش فرض طولانی مدت و برابر یک سال است. ما می‌خواهیم این مقدار پیش فرض را برای توکن‌های پروژه‌ که از نوع توکن دسترسی شخصی هستند، به یک روز تغییر دهیم. این کار را با متد ()boot در فایل AuthServiceProvider به صورت زیر انجام می‌دهیم.

<?php

namespace App\Providers;

use Carbon\Carbon;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        // 'App\Models\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Passport::routes();
        Passport::personalAccessTokensExpireIn(Carbon::now()->addHours(24));
    }
}

تا این‌جا تنظیمات موردنیاز Passport را به طور کامل انجام داده‌ایم. اکنون وقت آن فرا رسیده است که فرآیند احراز هویت کاربران را انجام دهیم.

ایجاد کنترلرها

ابتدا با اجرای دستور زیر، کنترلر AuthController را ایجاد می‌کنیم. این کنترلر، وظیفه‌ی پاسخگویی به درخواست‌های مربوط به ثبت نام و ورود کاربر را بر عهده دارد.

php artisan make:controller Api/v1/AuthController

دقت کنید که کنترلر را در مسیر app/Http/Controllers/Api/v1 ایجاد کرده‌ایم. پوشه‌ی Api را به کنترلرهای مربوط به وب‌سرویس‌ها اختصاص داده‌ایم. اما نکته‌ی اصلی، قرار دادن کنترلر در پوشه‌ی v1 است که مربوط به نسخه‌ی اولیه‌ی اپلیکیشنی است که ایجاد می‌کنیم. با انجام این کار، در صورت نیاز به ارائه‌ی نسخه‌های جدیدتر اپلیکیشن، کاربران نسخه‌های قدیمی‌تر، در اجرای اپلیکیشن با مشکلی مواجه نخواهند شد، چرا که هر نسخه، مسیرها و کنترلرهای مخصوص به خود را دارد.

ایجاد Resource

ویژگی Resource از نسخه‌ی 5.5، به لاراول اضافه شده است. Resource لایه‌ای است که بین مدل Eloquent و پاسخ Json خروجی قرار می‌گیرد و تبدیل اطلاعات مدل یا کالکشن مدل‌ها به خروجی Json را آسان می‌کند. همچنین می‌توانید اطلاعات مدل‌ها را به دلخواه خود فیلتر کنید. با اجرای دستور زیر یک Resource برای مدل User ایجاد می‌کنیم.

php artisan make:resource v1/UserResource

می‌بینید که Resource را در پوشه‌ی v1 قرار داده‌ایم تا بتوانیم Resource‌های نسخه‌های مختلف اپلیکیشن را از هم جدا کنیم. اکنون Resource ایجاد شده را به شکل زیر ویرایش کنید.

<?php

namespace App\Http\Resources\v1;

use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
        ];
    }
}

می‌توانید هرکدام از اطلاعات کاربر را که نیاز دارید، به شکل فوق در قالب یک آرایه‌ی Json برگردانید. نحوه‌ی استفاده از Resource ایجاد شده را در ادامه خواهید دید.

ایجاد متدها

اکنون متدهای موردنیاز را در کنترلر AuthController موجود در مسیر app/Http/Controllers/Api/v1، پیاده‌سازی می‌کنیم.

متد ثبت نام

<?php

namespace App\Http\Controllers\Api\v1;

use App\Http\Controllers\Controller;
use App\Http\Resources\v1\UserResource;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $data = $request->all();

        $validator = Validator::make($request->all(), [
            'name' => 'required|max:55|unique:users',
            'email' => 'required|email|unique:users',
            'password' => 'required|confirmed'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors()->first(), 422);
        }

        $data['password'] = bcrypt($request->password);

        $user = User::create($data);

        $accessToken = $user->createToken('UserToken')->accessToken;

        return response()->json([
            'user' => new UserResource($user),
            'token' => $accessToken,
            'token_type' => 'Bearer'
        ]);
    }
    
}

همان‌طور که می‌بینید، ابتدا اطلاعات ارسالی از سوی کاربر را اعتبارسنجی می‌کنیم. سپس رمز عبور ارسالی کاربر را با استفاده از تابع کمکی ()bcrypt رمزنگاری می‌کنیم. در ادامه کاربر جدید را ایجاد کرده و با استفاده از تابع کمکی ()createToken، توکن منحصربه‌فرد مربوط به کاربر را ایجاد می‌کنیم. این تابع در واقع، یک نمونه از کلاس PersonalAccessTokenResult را ایجاد می‌کند و توکن ایجاد شده در خصوصیت accessToken قابل دسترس است. این تابع به عنوان پارامتر اول، یک رشته را به عنوان نام توکن می‌پذیرد. این رشته یک نام دلخواه است. در پارامتر دوم نیز می‌توان یک آرایه را برای مشخص کردن scope‌های توکن به این تابع پاس داد که افزودن آن اختیاری است.

در ادامه نیز خروجی Json را به شکل آرایه، به سمت کلاینت ارسال می‌کنیم. در کلید اول این آرایه، یک نمونه از Resource را که ایجاد کرده‌ایم، قرار داده‌ و مدل کاربر ایجاد شده را نیز به آن پاس می‌دهیم. در کلید دوم توکن و در کلید سوم نوع توکن را قرار می‌دهیم. توکن‌های ایجاد شده در این حالت، از نوع Bearer هستند که در Authorization header درخواست قرار می‌گیرند. توکن‌های Bearer بخشی از استاندارد پروتکل 0Auth2 هستند.

متدهای ورود و خروج

پس از متد register، متد login و logout را نیز در همان کنترلر به شکل زیر تعریف می‌کنیم.

<?php

namespace App\Http\Controllers\Api\v1;

use App\Http\Controllers\Controller;
use App\Http\Resources\v1\UserResource;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $data = $request->all();

        $validator = Validator::make($request->all(), [
            'name' => 'required|max:55|unique:users',
            'email' => 'required|email|unique:users',
            'password' => 'required|confirmed'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors()->first(), 422);
        }

        $data['password'] = bcrypt($request->password);

        $user = User::create($data);

        $accessToken = $user->createToken('UserToken')->accessToken;

        return response()->json([
            'user' => new UserResource($user),
            'token' => $accessToken,
            'token_type' => 'Bearer'
        ]);
    }

    public function login(Request $request)
    {
        $data = $request->all();

        $validator = Validator::make($request->all(), [
            'email' => 'email|required',
            'password' => 'required'
        ]);
        
        if ($validator->fails()) {
            return response()->json($validator->errors()->first(), 422);
        }

        if (!auth()->attempt($data)) {
            return response()->json('ایمیل یا رمز عبور اشتباه است.', 422);
        }

        $user = auth()->user();
        $tokenResult = $user->createToken('userToken');
        $tokenModel = $tokenResult->token;
        if ($request->remember_me)
            $tokenModel->expires_at = Carbon::now()->addWeeks(1);
        $tokenModel->save();
        return response()->json([
            'user' => new UserResource($user),
            'token' => $tokenResult->accessToken,
            'token_type' => 'Bearer'
        ]);

    }

    public function logout(Request $request)
    {
        /** @var User $user
         */
        $request->user()->token()->revoke();
        return response()->json('شما با موفقیت خارج شدید.');
    }
}

با مشاهده‌ی متد login، می‌بینید که ابتدا ایمیل و رمز عبور ارسالی کاربر را اعتبارسنجی می‌کنیم. سپس با استفاده از تابع کمکی ()auth، عملیات احراز هویت را انجام می‌دهیم. نمونه‌ی ساخته شده از کلاس PersonalAccessTokenResult را در متغیر tokenResult ذخیره می‌کنیم. خصوصیت token در این کلاس، حاوی مدل رکورد ایجاد شده در جدول oauth_access_tokens در دیتابیس است که توکن‌های دسترسی شخصی را در خود ذخیره می‌کند. در صورتی که کاربر گزینه‌ی Remember Me یا مرا به خاطر بسپار را انتخاب کرده باشد، می‌توان تاریخ انقضای توکن ایجاد شده را به دلخواه تغییر داد. در اینجا ما تاریخ انقضا را برابر یک هفته قرار می‌دهیم و سپس با استفاده از متد ()save، مدل مربوطه را بروزرسانی می‌کنیم. در انتها نیز، مانند متد register، اطلاعات را در قالب آرایه‌ی Json به سمت کاربر ارسال می‌کنیم.

برای logout نیز ابتدا با استفاده از متد ()token، مدل رکورد مربوط به توکن ارسالی با درخواست کاربر را گرفته و با استفاده از متد ()revoke این مدل، آن را باطل می‌کنیم. سپس می‌توانیم یک پیام دلخواه نیز به سمت کلاینت ارسال کنیم.

ایجاد مسیرها

برای تکمیل فرآیند نوشتن وب‌سرویس‌ها، باید مسیرهای موردنیاز را به شکل زیر در فایل api.php در پوشه‌ی routes تعریف کنیم.

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/


Route::group(['prefix' => 'v1'], function (){
    Route::post('/register', [\App\Http\Controllers\Api\v1\AuthController::class, 'register']);
    Route::post('/login', [\App\Http\Controllers\Api\v1\AuthController::class, 'login']);

    Route::middleware('auth:api')->get('/logout', [\App\Http\Controllers\Api\v1\AuthController::class, 'logout']);
});

همان‌طور که می‌بینید، مسیرها را با استفاده از پیشوند v1 نسخه‌بندی کرده‌ایم تا در صورت ارائه‌ی نسخه‌ی بالاتر، مسیرهای مربوط به نسخه‌های قدیمی تحت تاثیر قرار نگیرند. هم‌چنین برای مسیر logout یا خروج، از یک Middleware با نام auth:api استفاده کرده‌ایم. شما می‌توانید  از این Middleware برای هر مسیری که نیاز به یک توکن معتبر دارد، استفاده کنید تا دسترسی به این مسیرها محدود شود. قسمت دوم نام این Middleware، مربوط به Guard تعریف شده در فایل AuthServiceProvider است. در صورتی که نیاز به احراز هویت انواع مختلفی از کاربران را دارید و هر نوع کاربر نیز از مدل Eloquent متفاوتی استفاده می‌کند، می‌توانید برای هر کدام، یک Guard در فایل AuthServiceProvider ایجاد کنید و سپس نام Guard دلخواه را در نام Middleware فوق جایگزین کنید.

تست وب‌سرویس‌ها

پس از اجرای مراحل فوق، اکنون باید وب‌سرویس‌هایی که ایجاد کرده‌ایم را تست کنیم. ما این کار را با استفاده از نرم‌افزار Postman انجام می‌دهیم. می‌توانید این نرم‌افزار را به صورت رایگان از وب سایت Postman دانلود کنید.

اجرای اپلیکیشن

ابتدا مطمئن شوید که با استفاده از Wamp یا Xampp، ماژول MySql را فعال کرده‌اید سپس، با استفاده از دستور زیر، اپلیکیشن را اجرا کنید.

php artisan serve

ثبت نام

نرم‌افزار Postman را باز کنید. با کلیک بر روی گزینه‌ی Create a request، یک پنجره‌ی ارسال درخواست ایجاد کنید. مسیر ثبت نام را در کادر مربوط به خود وارد کنید و متد Post را انتخاب کنید. در قسمت Body، با انتخاب x-www-form-urlencoded، پارامترهای لازم برای ثبت نام را وارد کنید. مقادیر پارامتر‌ها دلخواه هستند.

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

پس از کلیک بر روی گزینه‌ی Send، پاسخ موردنظر بنا به اطلاعات ارسالی به صورت آرایه‌ی Json به شما نشان داده می‌شود. در صورت رعایت کلیه‌ی نکات ذکر شده در این مقاله و همچنین استفاده از مقادیر فوق، پاسخ موفقیت‌آمیز به صورت زیر برایتان نمایش داده می‌شود.

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

در این حالت، یک کاربر با اطلاعات فوق در دیتابیس شما ایجاد شده است.

ورود

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

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

خروج

چه پس از ثبت نام و چه پس از ورود، در صورت دریافت موفقیت آمیز توکن، می‌توانید به تمام مسیرهای ویژه‌ی کاربران دسترسی داشته باشید. کافی است که توکن ایجاد شده را در در قسمت Header Authorization کپی کنید.

به عنوان مثال، برای ارسال درخواست خروج باید توکن ایجاد شده را به همراه درخواست خود به سمت سرور ارسال کنید. برای این منظور، یک پنجره‌ی جدید باز کرده و مانند قبل، مسیر را وارد و متد را انتخاب کنید. این بار، در قسمت Authorization، در سمت چپ و از منوی آبشاری  Type، گزینه‌ی Bearer Token را انتخاب کنید. سپس توکن را در کادر سمت راست کپی کنید. پس از کلیک بر روی گزینه‌ی Send، توکن با موفقیت باطل می‌شود.

جمع‌بندی:

در این مقاله از سری مقالات آموزش لاراول، نحوه‌ی احراز هویت وب‌سرویس‌های Restful را با ایجاد توکن‌های دسترسی شخصی و استفاده از پکیج Passport در لاراول آموختیم و توانستیم به صورت عملی با جزییات استفاده از این پکیج آشنا شویم. همچنین توانستیم وب سرویس‌های Restful ایجاد شده را با استفاده از نرم افزار Postman تست کنیم و از اجرای موفقیت آمیز آن‌ها مطمئن شویم. با شیوه‌ی نسخه‌بندی در نوشتن وب‌سرویس آشنا شدیم و نحوه‌ی ایجاد Resource برای تبدیل مدل یا کالکشن به خروجی Json را فراگرفتیم. شما به همین شیوه‌ی ذکر شده در این مقاله، می‌توانید وب‌سرویس‌های دلخواهتان را برای هر اپلیکیشنی که نیاز دارید، ایجاد کنید و با استفاده از ایجاد توکن‌های دسترسی شخصی، این وب‌سرویس‌ها را ایمن کنید.

خوشحال می‌شویم نظرات، تجربیات و سوالات خود را با ما و سایر کاربران سون لرن به اشتراک بگذارید.

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

چه امتیازی به این مقاله می دید؟
نویسنده رضا زیدی
از یادگیری ، عمل‌گرایی و چالش‌های مربوطه ، لذت می‌برم ...

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

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

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