آموزش استفاده از Passport لاراول برای اعتبارسنجی API

35 دیدگاه

فریم ورک Laravel متدهایی اعتبارسنجی (authentications) زیادی مثل Session, File, Token را برای مدیریت Login و Logout معمول کاربران پشتیبانی می کند ولی وقتی برنامه شما با درخواستی خارجی مثلا از طرف یک اپلیکیشن موبایل طرف است و روش لاگین معمولی پاسخگو نیست چه باید کرد؟

خوشبختانه لاراول از نسخه 5.3 به بعد ابزار Passport را (از OAuth2 پشتیبانی می کند) در اختیار ما گذاشت که بوسیله آن می توانیم درخواست های خارجی مثلا درخواست یک اپلیکیشن موبایل از برنامه مان را اعتبارسنجی کنیم و بتوانیم به آن اپلیکیشن پاسخ دهیم و مثلا لیست اطلاعات کاربر را به آن بفرستیم.

سوالی که خیلی از توسعه دهندگان لاراول می پرسند اینه که : خوب لاراول Passport ابزار خیلی خوبی برای اعتبارسنجی درخواست های ثانویه ارسالی به برنامه ماست ! ولی چطور اون رو پیاده سازی و استفاده کنیم ؟”

در این مقاله می خواهیم با یک مثال ساده نحوه کار با پاسپورت رو ببینیم .در این مثال ما فرض می کنیم شما می خواهید یک اپلیکیشن موبایل رو (آندروید یا iOS فرقی نمی کنه) به برنامه لاراول از طریق API وصل کنید . در این API کارهای زیر رو انجام خواهیم داد:

  • ورود کاربر : نام کاربری و رمز عبور کاربر در اپلیکیشن دریافت میشه و به لاراول ارسال میشه .لاراول اطلاعات رو اعتبارسنجی می کنه و اگر درست باشند ، یک Token ایجاد می کنه در برمی گردونه به اپلیکیشن والا خطای عدم دسترسی میده
  • ثبت نام کاربر : اطلاعات مورد نیاز در اپلیکیشن موبایل دریافت میشه و به لاراول ارسال میشه.لاراول کاربر رو به دیتابیس اضافه میکنه و Token دسترسی اون کاربر رو بر می گردونه.
  • دریافت اطلاعات کاربر وارد شده : بعد از انجام یکی از دو کار بالا(ورود یا ثبت نام) کاربر حالا وارد اپلیکیشن موبایل شده پس می تونه مثلا اطلاعات خودش رو ببینه . این کار باز از طریق ارسال یک درخواست به API و دریافت اطلاعات کاربر و نمایش اون در اپلیکیشن انجام میشه.
در همین رابطه :   امکان جدید لاراول 5.3 : Rollback کردن فقط یک Migration

دقت کنید که اعتبارسنجی در API با Login معمولی که یک فرم ورود می بینیم متفاوت هست.در API معمولا بعد از اینکه صحت نام کاربری و پسورد کاربر مشخص شد ، یک نشانه ورود بنام Token برای اون کاربر ایجاد میشه و این توکن به اپلیکیشن (ارسال کننده درخواست یا Client) ارسال میشه. از این به بعد این توکن به بین API (لاراول) و کلاینت (اپلیکیشن) دست به دست میشه و اعتبارسنجی درخواست از طریق این توکن انجام میشه و مثل لاگین معمولی خبری از session نیست.

نصب و تنظیم Passport

برای شروع باید Laravel Passport رو نصب کنیم. نصب هم طبق معمول از طریق Composer انجام میشه.پس خط فرمان رو باز کنید و دستور زیر رو وارد کنید تا بسته های مربوطه دانلود و نصب بشن.

composer require laravel/passport

حالا باید بسته را در بخش “Providers” فایل config/app.php ثبت کنیم :

Laravel\Passport\PassportServiceProvider::class,

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

php artisan migrate

بعد از اینکه جداول فوق ایجاد شدند نوبت به آخرین دستور می رسد تا نصب پاسپورت تمام شود:

php artisan passport:install

دستور فوق سرویس Passport را در لاراول نصب می کند و نیز کلیدهای رمزنگاری را ایجاد می کند تا پاسپورت بتواند Token های امنی را ایجاد کند.

حالا باید تریت “HasApiTokens” را به model کاربر اضافه کنید.فایل app/User.php رو باز کنید و در بالا این کد رو اضافه کنید:

use Laravel\Passport\HasApiTokens;

و این کد را داخل کلاس وارد کنید:

use HasApiTokens, Notifiable;

حالا شکل کلی کلاس User شبیه این خواهد بود:

<?php
namespace App;
 
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;
 
class User extends Authenticatable
{
    use Notifiable, HasApiTokens;
}

حالا فایل “app\Providers\AuthServiceProvider.php” رو باز کنید و خط زیر رو بالای صفحه اضافه کنید:

use Laravel\Passport\Passport;

و خط زیر رو داخل متد boot وارد کنید:

Passport::routes();

کد فوق route هایی که برای اعتبارسنجی Passport نیاز است را ایجاد می کند.

در همین رابطه :   آموزش کامل برنامه نویسی سایت تک صفحه ای با Vue.js و Laravel – قسمت 2

و حالا فایل “config/auth.php” رو باز کنید و در بخش api ، گزینه provider رو از token به passport تغییر بدید:

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

تبریک !!! تنظیمات passport به تمام رسید .

اضافه کردن Route های API

برای 3 کاری که در اول مطلب عرض شد باید مسیرها یا همان روت هایی را در فایل “routes\api.php” لاراول تعریف کنیم که به این صورت خواهند بود:

<?php

use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| 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(['namespace' => 'API'], function () {
    Route::get('/login', 'UserController@login');
    Route::get('/register', 'UserController@register');

});

Route::group(['middleware' => 'auth:api', 'namespace' => 'API'], function(){
    Route::post('details', 'UserController@details');
});

ایجاد Controller برای انجام کارها

همانطور که می بینید روت های فوق به کنترلر UserController اشاره می کنند . پس باید این کنترلر را نیز ایجاد کنیم . برای این کار دستور زیر را در خط فرمان وارد کنید:

php artisan make:controller API\UserController

حالا به مسیر “app\Http\Controllers\API\UserController.php” رفته و کد های زیر را داخل آن وارد کنید:

<?php

namespace App\Http\Controllers\API;

use App\Client;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Support\Facades\Auth;
use Validator;

class UserController extends Controller
{

    public $successStatus = 200;

    /**
     * login api
     *
     * @return \Illuminate\Http\Response
     */
    public function login(){
        if(Auth::attempt(['mobile' => request('mobile'), 'password' => request('password'), 'type' => 2])){
            $user = Auth::user();
            $success['token'] =  $user->createToken('MyApp')->accessToken;
            return response()->json(['success' => $success], $this->successStatus);
        }
        else{
            return response()->json(['error'=>'Unauthorised'], 401);
        }
    }

    /**
     * Register api
     *
     * @return \Illuminate\Http\Response
     */
    public function register(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required',
            'email' => 'required|email',
            'mobile' => 'required',
            'password' => 'required',
        ]);

        if ($validator->fails()) {
            return response()->json(['error'=>$validator->errors()], 401);
        }

        $input = $request->all();
        $input['password'] = bcrypt($input['password']);
        $input['type'] = 2;
        $user = User::create($input);
        $success['token'] =  $user->createToken('MyApp')->accessToken;
        $success['name'] =  $user->name;

        return response()->json(['success'=>$success], $this->successStatus);
    }

    /**
     * details api
     *
     * @return \Illuminate\Http\Response
     */
    public function details()
    {
        $user = Auth::user();
        return response()->json(['success' => $user], $this->successStatus);
    }
}

بروزرسانی جدول Users

به علاوه نیاز است در Migration جدول users نیز تغییراتی بدهید و فیلد api_token رو اضافه کنید.

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique()->nullable();
            $table->string('mobile')->unique()->nullable();
            $table->string('password');
            $table->string('os')->nullable();
            $table->string('os_version')->nullable();
            $table->string('api_token', 60)->unique()->nullable();
            $table->string('code')->nullable();
            $table->tinyInteger('type')->default(1);
            $table->tinyInteger('status')->default(1);
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

تست API

همانطور که می بینید این کنترلر شامل 3 متد برای انجام 3 کاری است که در بالا ذکر کردیم.برای تست کارکرد API می توانید از برنامه PostMan استفاده کنید و درخواست های مورد نظرتان را به آدرس API ارسال کنید.مثلا برای تست login به شکل زیر می توانید عمل کنید:

در همین رابطه :   آشنایی با اصول REST و برنامه نویسی RESTful API های وب

هنگام تماس با api دقت کنید که “Accept : application/json” را نیز همراه Header درخواست ارسال کنید تا لاراول به جای نمایش HTML به شما خروجی JSON ارائه دهد دقیقا همان چیزی که اپلیکیشن موبایل به آن نیاز دارد.

بعد از اجرای موفقیت آمیز شما مثل تصویر بالا خروجی شامل یک Token طولانی خواهید دید.کافیست این توکن را کپی کنید چون برای اجرای درخواست بعدی یعنی گرفتن اطلاعات کاربر به آن نیاز داریم.

در تصویر بالا مثل بخش قبل به api متصل شدی مولی برای گرفتن اطلاعات کاربر لاگین کرده . به بخش headers نیز توجه کنید که 2 مورد Accept و Authorization حتما نیاز است.توکنی که در بخش قبل بعد از لاگین کپی کرده بودیم باید در بخش Authorization و بعد از کلمه “Bearer” کپی کنیم .

برای برنامه و api خودتون می تونید کنترلرها و روت های دیگه ای هم اضافه کنید و به همین صورتی که دیدید استفاده کنید.

همین ! ایجاد api در لاراول و اضافه کردن لاگین به آن در لاراول خیلی ساده بود و امیدوارم بتونید استفاده کنید و مفید باشه .

 

دسته بندی : Laravel

35 نظر

  1. بازتاب: Passport لاراول برای اعتبارسنجی API - وب-سرویس - API.ir
  2. سلام
    جدول یوزر من فیلد ایمیل رو نداره و کلاً احراز هویت با شماره موبایل باید انجام بشه چجوری به پاسپورت این رو بفهمونم ؟

  3. باسلام
    برای استفاده از پاسپورت در حالت multi auth باید چکاری انجام داد اپ من باید سه نوع کاربر patient و nurse و doctor رو داشته باشه اگر راهنمایی بفرمایید ممنون میشم

  4. با سلام و عرض خسته نباشید

    ممنون از آموزش خوب و مفیدتون ای کاش آموزش multi auth رو هم برای api قرار میدادید من الان میخوام برای سه نوع کاربر اقدام کنم patient و nurse و doctor ولی در همون کاربر اول به مشکل خوردم چون آدرس لاگین من http://project.test/api/patient/login هستش و وقتی کاربر patient لاگین میکنه و برای درخواست های بعدی توکن را هم در هدر قرار میدم ولی خود پاسپور میاد دنبال آدرس http://project.test/api/login میگرده تا توکن رو چک کنه و بعد عمل بعدی رو انجام بده و چون این مسیر وجود نداره پیام Route [login] not defined رو نشون میده :(((
    اگر راهنمایی کنید ممنون میشم

  5. خیلی ممنون از آموزش خوبتون فقط چند نکته هست که باید توی کدا رعایت بشه
    1. زمانی که ادرس ایمیل کاربر از قبل ثبت شده باشه ارور sql رو برمیگردونه برای حل این مشکل کد قسمت register کنترلر یوزر api رو به این صورت تغییر بدید :

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

    2.در فایل “routes\api.php” شما باید دو خط زیر رو از get به post تغییر بدهید تا موقع ارسال اطلاعات با ارور مواجه نشوید.

    Route::post('/login', 'UserController@login');
    Route::post('/register', 'UserController@register');

    3. دوستانی که توکن اونها ذخیره نمیشه باید از قسمت مدل دیتابیسشون فیلد توکن رو اضافه کنند

  6. سلام ممنون بابت آموزش خوبتون
    اونوقت این توکن تا چند روز معتبره ؟
    فکر کنم فیلد api_token که گذاشتین از طرف کلاینتی مانند اندروید استودیو پر میشه ، وقتی که لاگین شد token را در api_token ذخیره می کنه ، درسته؟

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

  7. عالی بود
    فقط ی سوال دارم من
    متد register رو چطوری باید از داخل اپ فرخوانی کرد
    منظورم پاس دادن اطلاعات از اپ به متد هستش
    نوع متد get درنظر گرفته شده

  8. با تشکر از آموزش عالی .. سوالی دارم :
    بعد از هر بار لاگین یوزر یه توکن جدید میده .. اما هم با توکن قبلی میشه کار کرد هم با این توکن جدید ( در بخش details )
    آیا این ایرادی نداره نداره ؟ آخه اون قبلی باید حذف شه . . .

  9. سلام. از کجا می تونم برای یه روت خاص درخواست های مربوط به اکشن پست رو بدون توکن ارسال کنم؟ با تشکر

  10. سلام مرسی از آموزش
    آقا من قدم به قدم و خط به خط عین چیزایی که گفته رو انجام میدم ولی هیچی اجرا نمیشه و کلا ارور برمیگرده تو postMan
    لاراول 5.5
    باید چیکار کرد؟

    1. سلام علی آريالا مشکل قبلی حل شد
      حالا مشکل اینه که من نمیدونم این api_token رو باید خودم پر کنم ینی آپدیت کنم یا خودش پر میشه؟
      چون من تو کدا ندیدم جایی api_token آپدیت بشه

      و اینکه اگه ممکنه یه راه ارتباطی تو تلگرام بدید

      1. شکر خدا . این فیلد به نظرم خود سیستم دستکاری می کنه و شما نیاز نیست کاری بکنید. برای اطمینان می تونید یه بار از طریق api کاربر ایجاد کنید و مقدار این فیلد رو چک کنید

        تلگرام : @AliZamani

  11. بابت آموزشی که گذاشتید بسیار ممنونم
    فقط یک نکته را هم بهش اضافه کنید که باید قبل از استفاده نامی را برای اطلاعات شخصی لاراول پاسپورت تعیین نمود و از آن نام در گرفتن توکن استفاده کرد. دستور مورد استفاده :
    php artisan passport:client –personal

    1. سلام . خیلی ممنونم بابت این نکته که فرمودید کاش کمی بیشتر توصیح می دادید درباره این کد و اینکه حتما لازمه استفاده کنیم یا نه ؟ تا اونجایی که یادمه من استفاده نکردم از این دستور

  12. سلام
    فیلدایی که برای مایگریشن user گزاشتین ثابت هستش؟
    ینی همه اون هارو باید اضافه کنیم به جدولمون؟

    1. سلام . خیر فقط email, password و api_token فکر می کنم ضروری باشن و بقیه فقط در این مثالی که نوشتیم کاربرد دارن

  13. سلام من همه قسمت هارو انجام دادم ولی الان وقتی رجیستر میکنم اطلاعات موبایل و توکن و type ذخیره نمیشن
    از laravel 5.5 استفاده کردم

  14. سلام و درود من بعد از انجام تمام مراحل توکن رو دریافت میکنم و به ادرس details ارسال میکنم ولی
    پاسخی دیافت نمیکنم و همش با Could not get any response مواجه میشم اگر امکانش هست راهنمایی کنید

    1. سلام .
      مثل دوستی که در نظرات گفتن همین مشکل شما رو داشتن چون یک space در هدر بوده.شما این مورد رو چک کردید ؟

  15. مشکل Could not get any response حل شد، به خاطر بودن space تو هدر ارسالی بود.
    تو تابع details هیچی برنمیگردونه، null میده، در صورتی که تو تابع login درست بوده اطلاعات و کاربر لاگین شده. تو جدول user هم توکنی ثبت نمیشه! لطفا راهنمایی کنید. ممنون

  16. سلام
    وقتی به روت details درخواست میفرستم این خطا را می دهد؟
    SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘api_token’ in ‘where clause’ (SQL: select * from `users` where `api_token` = eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjQ3MWJhNDU4YWNjY2RlNTU4ZTRlYmUwY2U3OTFjMmMzNDhiMDhjZjAxOTYxMGRkZWEyNTk4ZGU2NTBiYzJlYTM5NzZmZWVmMDgyZjlhODdhIn0 limit 1)

    1. سلام . باید فیلد api_token رو به Migration کاربر اضافه کنین . من کد کامل migration خودم رو به مقاله اضافه کردم می تونید ببینید

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

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