سلام و وقت بخیر
من دو تا guard توی پروژه خودم دارم. api و admin.
هر دوی ای گارد ها با درایور laravel passport کانفیگ شدن. اسم جداول هم فرق میکنه . جداول من اینهاست : users و admins
حالا یه اتفاق خیلی وحشتناک افتاده!
اگر یک کاربر معمولی با ایدی 1 توی سیستم لاگین کنه و اکسس تاکن بگیره میتونه به حساب کاربری ادمین شماره 1 دسترسی داشته باشه ! و به همین شکل کاربر شماره 2 میتونه به حساب کاربری ادمین شماره 2 !!!!!
این موضوع خیلی وحشتناکه و من بارها سرچ کردم و هیچ چیزی توی نت در موردش پیدا نکردم!
ممنون میشم اگه بررسی داشته باشید و راهنماییم کنید
محتوای فایل config/auth.php :
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
'hash' => false,
],
'admin' => [
'driver' => 'passport',
'provider' => 'admins',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
]
],
وقتی کاربر (گارد api) کد ملی و کد فعال سازیشو وارد میکنه من میام و یه اکسس تاکن برای کاربر میسازم :
$accessToken = $user->createToken('User login')->accessToken;
و این اکسس تاکن رو توی ریسپانس به کاربر برمیگردونم .
وقتی هم ادمین با نام کاربری و پسورد لاگین میکنه به همین شکل کار میکنم :
$username = $this->request->get('username');
$password = $this->request->get('password');
if (! $admin = AdminRepository::getInstance()->checkUsernameAndPassword($username, $password))
throw new InvalidAuthAdminException();
$accessToken = $admin->createToken('admin')->accessToken;
توی فایل routes/api.php هم دسترسی به روت ها رو اینطوری چک میکنم :
Route::group(['middleware' => ['auth:api']], function() {}(;
Route::group(['middleware' => ['auth:admin']], function() {}(;
الان در صورتی که کاربر با هر کدوم از گارد ها آتنتیکیت کرده باشه چنانچه توی هر دو جدول (جدول کاربران و ادمین ها) آیدیش موجود باشه هر دو کد زیر true برگردونده میشن!!!!
Auth::guard('api')->check()
Auth::guard('admin')->check()
من این موضوع رو توی پروژه های زیادی چک کردم و همه این باگ وحشتناک رو دارن و ظاهرا خیلی از برنامه نویسها ازین موضوع بی خبر هستن.
ممنون میشم یه نفر راهنمایی کنه.
من توی این پروژه از scopes استفاده نکردم
این باگ passport نیست. استفاده غیر اصولی شما باعث ایجاد این باگ شده. داکیومنت های پکیج رو یکبار دیگه از اول همشو بخونید.
@khanzadimahdi توی داکیومنت لاراول اینرو گفته منم همین کارو کردم
https://laravel.com/docs/8.x/passport#multiple-authentication-guards
کار دیگه ای هم باید انجام میدادم؟
پکیج یه table داره که اونجا access token ها رو ذخیره میکنه و همونجا یه user_id هم درج میشه! حالا شما میای اونو morph میکنی به چندتا جدول درصورتی که اصلا relation که براش درنظر گرفته میشه morph نیست.
اگه دقت کنی براش فقط id مهمه و اینکه با کدوم نوع از User (که قطعا جدول های متفاوت براش ساختین) ارتباط داره اهمیت نمیده
حالا فرض کن سه تا table داری واسه 3 نوع یوزری که استفاده کردی! همشون هم id = 1 رو دارن! خب حالا اگه بین access_tokens و اون جدول مورد نظرت join بزنیم صرف نظر از اینکه نوع User مهم باشه میره یه ایدی 1 پیدا میکنه میگیره میاره بیرون و لاگین میکنه.
توی داکیومنت راجب گارد های مختلف گفته و مدل های مختلف واسه یوزر! راجب اینکه جدول های متفاوت استفاده کنید چیزی نگفته!
شما اگه میخوای از پاسپورت استفاده کنی باید همه یوزر ها رو توی یه table ذخیره کنی یا اینکه relation های پاسپورت رو دستکاری کنی و کاستوم کنی بر اساس نیازت.
@khanzadimahdi این مشکل رو من توی دو سه تا پروژه ی دیگه که دوستتان دیگه نوشته بودن دیدم! خیلی خیلی وحشتناکه این موضوع!
و خب وقتی لاراول ادعا میکنه که پکیج پاسپورت از multiple guard پشتیبانی میکنه و وقتی توی فایل کانفیگ ما ذکر میکنیم که مثلا گارد admin اسم جدولش اینه ، پس این موضوع یه باگ از سمت لاراول هست که احتمالا توی پروزه های بیشماری مخفی مونده !
اکثرا در زمان شروع یک پروژه، جدا کردن جدول کاربرهای مختلف (ادمین، اپراتور و کاربر عادی) ایده خوب و جذابی به نظر میرسه
اما با بزرگ تر شدن پروژه ، پیچیدگی هایی هم به وجود میاد
سوای پیچیدگی ها، از این جهت بهش فکر کن که
ادمین هم یک کاربره که باید همون اطلاعات کاربر عادی براش ذخیره بشه
تنها چیزی که اضافه داره سطح دسترسی هاش به سیستم هست
که میتونی با یه سیستم Role/Permission مدیریتش کنی
حتی میتونی یه سیستم سطح دسترسی ساده برای خودت بنویسی
منظورم این نیست که این راه ، تنها راه درسته
اما برای ۹۵٪ پروژه ها منطقی ترین روش ممکن هست
یه راهکاری که هست اینه که شما تمام کاربرا رو توی ۱ جدول ذخیره کنی
و بعد اگر خواستی چند تا گارد هم داشته باشی، مشکلی نیست
تمام گاردها باز هم میتونند از یه جدول استفاده کنند
به این ترتیب ID ها یونیک هستند و مشکلی که اشاره کردی، پیش نمیاد
درباره این موضوع هم، که این ماجرا باگ هست یا ویژگی که شاید شما ازش بی خبری
میتونی توی بخش issue های لاراول در گیتهاب موضوع رو عنوان کنی و کدهای ReProduce کردن این حالت رو هم منتشر کنی
اگر باگ باشه حتما برطرف میشه
اگر هم مشکل در نوع استفاده از Passport باشه، که عنوان میشه
حتی اگر راهکاری برای حل این موضوع سراغ داری میتونی کدش رو بنویسی و Pull Request بزنی
آیا مایل به ارسال نوتیفیکیشن و اخبار از طرف راکت هستید ؟