فریم ورک Laravel متدهایی اعتبارسنجی (authentications) زیادی مثل Session, File, Token را برای مدیریت Login و Logout معمول کاربران پشتیبانی می کند ولی وقتی برنامه شما با درخواستی خارجی مثلا از طرف یک اپلیکیشن موبایل طرف است و روش لاگین معمولی پاسخگو نیست چه باید کرد؟
خوشبختانه لاراول از نسخه 5.3 به بعد ابزار Passport را (از OAuth2 پشتیبانی می کند) در اختیار ما گذاشت که بوسیله آن می توانیم درخواست های خارجی مثلا درخواست یک اپلیکیشن موبایل از برنامه مان را اعتبارسنجی کنیم و بتوانیم به آن اپلیکیشن پاسخ دهیم و مثلا لیست اطلاعات کاربر را به آن بفرستیم.
سوالی که خیلی از توسعه دهندگان لاراول می پرسند اینه که : خوب لاراول Passport ابزار خیلی خوبی برای اعتبارسنجی درخواست های ثانویه ارسالی به برنامه ماست ! ولی چطور اون رو پیاده سازی و استفاده کنیم ؟”
در این مقاله می خواهیم با یک مثال ساده نحوه کار با پاسپورت رو ببینیم .در این مثال ما فرض می کنیم شما می خواهید یک اپلیکیشن موبایل رو (آندروید یا iOS فرقی نمی کنه) به برنامه لاراول از طریق API وصل کنید . در این API کارهای زیر رو انجام خواهیم داد:
- ورود کاربر : نام کاربری و رمز عبور کاربر در اپلیکیشن دریافت میشه و به لاراول ارسال میشه .لاراول اطلاعات رو اعتبارسنجی می کنه و اگر درست باشند ، یک Token ایجاد می کنه در برمی گردونه به اپلیکیشن والا خطای عدم دسترسی میده
- ثبت نام کاربر : اطلاعات مورد نیاز در اپلیکیشن موبایل دریافت میشه و به لاراول ارسال میشه.لاراول کاربر رو به دیتابیس اضافه میکنه و Token دسترسی اون کاربر رو بر می گردونه.
- دریافت اطلاعات کاربر وارد شده : بعد از انجام یکی از دو کار بالا(ورود یا ثبت نام) کاربر حالا وارد اپلیکیشن موبایل شده پس می تونه مثلا اطلاعات خودش رو ببینه . این کار باز از طریق ارسال یک درخواست به API و دریافت اطلاعات کاربر و نمایش اون در اپلیکیشن انجام میشه.
دقت کنید که اعتبارسنجی در 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 نیاز است را ایجاد می کند.
و حالا فایل “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 به شکل زیر می توانید عمل کنید:
هنگام تماس با api دقت کنید که “Accept : application/json” را نیز همراه Header درخواست ارسال کنید تا لاراول به جای نمایش HTML به شما خروجی JSON ارائه دهد دقیقا همان چیزی که اپلیکیشن موبایل به آن نیاز دارد.
بعد از اجرای موفقیت آمیز شما مثل تصویر بالا خروجی شامل یک Token طولانی خواهید دید.کافیست این توکن را کپی کنید چون برای اجرای درخواست بعدی یعنی گرفتن اطلاعات کاربر به آن نیاز داریم.
در تصویر بالا مثل بخش قبل به api متصل شدی مولی برای گرفتن اطلاعات کاربر لاگین کرده . به بخش headers نیز توجه کنید که 2 مورد Accept و Authorization حتما نیاز است.توکنی که در بخش قبل بعد از لاگین کپی کرده بودیم باید در بخش Authorization و بعد از کلمه “Bearer” کپی کنیم .
برای برنامه و api خودتون می تونید کنترلرها و روت های دیگه ای هم اضافه کنید و به همین صورتی که دیدید استفاده کنید.
همین ! ایجاد api در لاراول و اضافه کردن لاگین به آن در لاراول خیلی ساده بود و امیدوارم بتونید استفاده کنید و مفید باشه .
سلام
جدول یوزر من فیلد ایمیل رو نداره و کلاً احراز هویت با شماره موبایل باید انجام بشه چجوری به پاسپورت این رو بفهمونم ؟
باسلام
برای استفاده از پاسپورت در حالت multi auth باید چکاری انجام داد اپ من باید سه نوع کاربر patient و nurse و doctor رو داشته باشه اگر راهنمایی بفرمایید ممنون میشم
با سلام و عرض خسته نباشید
ممنون از آموزش خوب و مفیدتون ای کاش آموزش multi auth رو هم برای api قرار میدادید من الان میخوام برای سه نوع کاربر اقدام کنم patient و nurse و doctor ولی در همون کاربر اول به مشکل خوردم چون آدرس لاگین من http://project.test/api/patient/login هستش و وقتی کاربر patient لاگین میکنه و برای درخواست های بعدی توکن را هم در هدر قرار میدم ولی خود پاسپور میاد دنبال آدرس http://project.test/api/login میگرده تا توکن رو چک کنه و بعد عمل بعدی رو انجام بده و چون این مسیر وجود نداره پیام Route [login] not defined رو نشون میده :(((
اگر راهنمایی کنید ممنون میشم
خیلی ممنون از آموزش خوبتون فقط چند نکته هست که باید توی کدا رعایت بشه
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. دوستانی که توکن اونها ذخیره نمیشه باید از قسمت مدل دیتابیسشون فیلد توکن رو اضافه کنند
سلام ممنون بابت آموزش خوبتون
اونوقت این توکن تا چند روز معتبره ؟
فکر کنم فیلد api_token که گذاشتین از طرف کلاینتی مانند اندروید استودیو پر میشه ، وقتی که لاگین شد token را در api_token ذخیره می کنه ، درسته؟
سلام . می تونید از تنظیمات پاسپورت مدت اعتبار رو مشخص کنید که در مستندات سایت لاراول هست. بله کلاینت اول یوزر و پسورد رو می فرسته و توکن رو دریافت می کنه و بعدا توکن رو می فرسته فقط با هر درخواستی
بسیار عالی. ممنون از آموزش کاملتون.
عالی بود
فقط ی سوال دارم من
متد register رو چطوری باید از داخل اپ فرخوانی کرد
منظورم پاس دادن اطلاعات از اپ به متد هستش
نوع متد get درنظر گرفته شده
با تشکر از آموزش عالی .. سوالی دارم :
بعد از هر بار لاگین یوزر یه توکن جدید میده .. اما هم با توکن قبلی میشه کار کرد هم با این توکن جدید ( در بخش details )
آیا این ایرادی نداره نداره ؟ آخه اون قبلی باید حذف شه . . .
خوشحالم مفید بوده براتون . تا اونجایی که یادمه می تونید توکن های قبلی رو پاک کنین اگه خواستین
اینم ببینین بد نیست: https://stackoverflow.com/a/48069525
سلام. از کجا می تونم برای یه روت خاص درخواست های مربوط به اکشن پست رو بدون توکن ارسال کنم؟ با تشکر
سلام . می تونید کنار login و register قرار بدید .
سلام مرسی از آموزش
آقا من قدم به قدم و خط به خط عین چیزایی که گفته رو انجام میدم ولی هیچی اجرا نمیشه و کلا ارور برمیگرده تو postMan
لاراول 5.5
باید چیکار کرد؟
سلام دوست عزیز
چه خطایی ؟
سلام علی آريالا مشکل قبلی حل شد
حالا مشکل اینه که من نمیدونم این api_token رو باید خودم پر کنم ینی آپدیت کنم یا خودش پر میشه؟
چون من تو کدا ندیدم جایی api_token آپدیت بشه
و اینکه اگه ممکنه یه راه ارتباطی تو تلگرام بدید
شکر خدا . این فیلد به نظرم خود سیستم دستکاری می کنه و شما نیاز نیست کاری بکنید. برای اطمینان می تونید یه بار از طریق api کاربر ایجاد کنید و مقدار این فیلد رو چک کنید
تلگرام : @AliZamani
بابت آموزشی که گذاشتید بسیار ممنونم
فقط یک نکته را هم بهش اضافه کنید که باید قبل از استفاده نامی را برای اطلاعات شخصی لاراول پاسپورت تعیین نمود و از آن نام در گرفتن توکن استفاده کرد. دستور مورد استفاده :
php artisan passport:client –personal
سلام . خیلی ممنونم بابت این نکته که فرمودید کاش کمی بیشتر توصیح می دادید درباره این کد و اینکه حتما لازمه استفاده کنیم یا نه ؟ تا اونجایی که یادمه من استفاده نکردم از این دستور
وقت بخیر
اون فیلد api_token واسه چیه که توی جدول یوزرز گذاشتید؟
ممنونم دوست عزیز . اگه درست یادم باشه برای ذخیره توکن کاربره
سلام
فیلدایی که برای مایگریشن user گزاشتین ثابت هستش؟
ینی همه اون هارو باید اضافه کنیم به جدولمون؟
سلام . خیر فقط email, password و api_token فکر می کنم ضروری باشن و بقیه فقط در این مثالی که نوشتیم کاربرد دارن
بعد اینکه آدرس routای که داخل postman وارد میکنیم چی هستش؟
localhost/login ?
سلام من همه قسمت هارو انجام دادم ولی الان وقتی رجیستر میکنم اطلاعات موبایل و توکن و type ذخیره نمیشن
از laravel 5.5 استفاده کردم
این مشکل احتمالا به پاسپورت مربوط نیست و در نحوه ذخیره اطلاعات در دیتابیس مشکلی باید باشه
سلام و درود من بعد از انجام تمام مراحل توکن رو دریافت میکنم و به ادرس details ارسال میکنم ولی
پاسخی دیافت نمیکنم و همش با Could not get any response مواجه میشم اگر امکانش هست راهنمایی کنید
سلام .
مثل دوستی که در نظرات گفتن همین مشکل شما رو داشتن چون یک space در هدر بوده.شما این مورد رو چک کردید ؟
مشکل Could not get any response حل شد، به خاطر بودن space تو هدر ارسالی بود.
تو تابع details هیچی برنمیگردونه، null میده، در صورتی که تو تابع login درست بوده اطلاعات و کاربر لاگین شده. تو جدول user هم توکنی ثبت نمیشه! لطفا راهنمایی کنید. ممنون
توکن که از لاگین گرفتید به متد details ارسال می کنید ؟
بله ارسال میکنم، طبق همون چیزی که تو سایت گفتید.
خوب دقیقا چی بر می گردونه ؟ فقط null یا مثلا success : null ؟
توی بخش آخر که توکن رو ارسال میکنیم، postman خطا میده: Could not get any response دلیلش چیه؟
سلام
وقتی به روت details درخواست میفرستم این خطا را می دهد؟
SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘api_token’ in ‘where clause’ (SQL: select * from `users` where `api_token` = eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjQ3MWJhNDU4YWNjY2RlNTU4ZTRlYmUwY2U3OTFjMmMzNDhiMDhjZjAxOTYxMGRkZWEyNTk4ZGU2NTBiYzJlYTM5NzZmZWVmMDgyZjlhODdhIn0 limit 1)
سلام . باید فیلد api_token رو به Migration کاربر اضافه کنین . من کد کامل migration خودم رو به مقاله اضافه کردم می تونید ببینید