محمدرضا فلکی
6 ماه پیش توسط محمدرضا فلکی مطرح شد
10 پاسخ

چگونه کاربر رو از روی توکن پیدا کنم

سلام
من از پکیج sanctum استفاده میکنم و نیاز دارم user رو از روی api_token بگیرم ولی مشکل اینه که user و api_token روی دوتا table جدا هستن
و جدول personal_access_tokens مدلی نداره که با مدل user در رابطه باشه.
میخواستم بدونم چه شکلی میشه حلش کرد؟


ثبت پرسش جدید
محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 6 ماه پیش مطرح شد
0

داداش گلم قطعه کد اول برای کمک گرفتن بود که گفتم از روش فهمیدم هم هش شده هم پایپ باید حذف بشه
قطه کد دوم کل چیزی بود ک شما نیاز داری و فقط همون و باید استفاده کنی

        $cookieWithPipe=$request->cookie('your_token_cookie_name');
        [$id, $tokenWithoutPipe] = explode('|', $cookieWithPipe, 2);
        $token = \Laravel\Sanctum\PersonalAccessToken::where('token', hash('sha256', $tokenWithoutPipe))->first();
        $user = $token->tokenable;
        return $user;

شما سوالتون اینه که من توکنی دارم و میخوام از روی توکن کاربر خودم رو پیدا کنم
توکن من توی پروژم از کوکی ها خونده میشه (میدلوری دارم که کوکی رو میزاره توی هدر که کاری به اینجاش نداریم)
در کل خط اول کد من توکن هست همین

$cookieWithPipe=$request->cookie('your_token_cookie_name');

من نوشتم your_token_cookie_name یعنی بیا اسم کوکی خودتو بنویس که توکن توشه
برای شما انگاری توی $token = $request->bearerToken() هست کوکی پس اصلا نیاز به خط اول کد من نداری
توکن خودت رو dd بگیر همین اول اول ببین آیا پایپ داره ؟ ( | ) همین علامتی که توی پرانتر هست منظورمه
اگر داره مثل خط زیر اگر بود خروجی شما

17|mNymifftkRZkGwAw4KkrWIVAmgadUOhsnDylqnBff7a4a755

یعنی نیاز هست که از اون بخش explode استفاده کنی تا جداش کنی و عدد قبلشم حذف کنی اگر نبود خب نیازی بهش نداری

[$id, $tokenWithoutPipe] = explode('|', $cookieWithPipe, 2);

حالا تا اینجا فقط ما توکن رو فقط گرفتیم و هیچ کار خاصی نکردیم اصلا
جدول توکن های ایجاد شده چون رمزنگاری شده و هش شده ما هم میاییم این توکن رو هش میکنیم و فقط به همین رکورد از جدول میرسیم

$token = \Laravel\Sanctum\PersonalAccessToken::where('token', hash('sha256', $tokenWithoutPipe))->first();

حالا این کالکشن دریافتی از مدل personalAccessToken به ما کاربر رو میده

$user = $token->tokenable;

تموم
کد من دقیقا اینه

    public function user(Request $request)
    {
        $cookieWithPipe=$request->cookie('board_info_login_token');
        [$id, $tokenWithoutPipe] = explode('|', $cookieWithPipe, 2);
        $token = \Laravel\Sanctum\PersonalAccessToken::where('token', hash('sha256', $tokenWithoutPipe))->first();
        $user = $token->tokenable;
        return $user;
    }

و خروجی اون یوزر منه که میبینی در زیر

{
    "id": 2500,
    "fullName": "\u0634\u0631\u06a9\u062a \u0627\u0646\u0641\u0648\u0631\u0645\u0627\u062a\u06cc\u06a9 \u0633\u067e\u0646\u062a\u0627",
    "username": "sepanta",
    "email_verified_at": null,
    "mobileNumber": null,
    "is_professor": 0,
    "created_at": null,
    "updated_at": null
}

هیچ کد اضافی نداره
مشکل شما در کد ، توکنته
باید توکن رو پیدا کنی توی کد خودت که کجا داری میفرستی و به چه شکل داری ازش استفاده میکنی همین
طبق کدی که من از شما میبینم کد زیر باید برات مناسب باشه

        $cookieWithPipe=$request->bearerToken();
        [$id, $tokenWithoutPipe] = explode('|', $cookieWithPipe, 2);
        $token = \Laravel\Sanctum\PersonalAccessToken::where('token', hash('sha256', $tokenWithoutPipe))->first();
        $user = $token->tokenable;
        return $user;

ولی شما نیاز داری که مقدار $request->bearerToken(); رو خروجی بگیری و مطمین بشی که توکن توش هست و با پایپ هست تا کد بالا کار کنه
اگر نبود باید مرحله جدا سازی عدد و پاپ رو هم فاکتور بگیری

برای من توکن توی کوکی هست و توسط میدلور میام میزارمش توی هدر درخواستم دلیلشم اینه که از کوکی با نوع httpOnly دارم استفاده میکنم که درخواستم امن باشه و توکن قابل مشاهده نباشه توسط مرور گر


محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 6 ماه پیش مطرح شد
0

سلام
من خودم میخواستم همچین کاری بکنم ولی دیدم به اذیتیش نمیرزه و هر دو جدول رو یکی کردم
یعنی یه جدول کاربر داری با سطح دسترسی حالا میتونی اطلاعات تکمیلی رو توی جداول دیگه قرار بدی براشون هرچی که هست
اما چیزی که میخوایی و نیازته باید به لاراول سنکتوم بگی اقا من یه جدول دیگه دارم یا جند تا دیگه اصلا
باید بهش معرفی کنی ثبت کنی و میدلور و داستاناش
چند تا سایت رو برات لینک میکنم و عملا یکیه همشون راه حلش اما جون ممکنه تغییراتی داشته باشه و ریز تر باشه میزارم خودت بررسی کن و مجدد سرچ کن مثل چیزی که میبینی
من انجام ندادم خودم اما در هر صورت احتمالا به کارت بیاد
سایت یک
سایت دو
سایت سه


حسین افتخارراد
تخصص : نال کد
@hosseinradvictor 6 ماه پیش مطرح شد
0

میدلور تون رو روی aurh:sanctum قرار بدید و api دریافتی شامل هدر توکن کاربر باشه عملیات خود اتوماتیک انجام میشه و کاربر فایند میشه نیاز نیست شما کاری بکنید فقط میتونید از دستور auth() برای دسترسی به کاربری که لاگ کرده استفاده کنید


محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 6 ماه پیش مطرح شد
0

@hosseinradvictor
من فک کردم ایشون از دو جدول برای لاگین کردن استفاده میکنن عذرخواهم

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

$token=$user->createToken('token'.$user->id)->plainTextToken;

بعد از ایجاد و لاگین خیلی راحت به شکل زیر کاربر لاگین شده رو میتونی دریافت کنی

Auth::user();

برای لاگ اوت هم به روش زیر

Auth::user()->currentAccessToken()->delete();

محمدرضا فلکی
تخصص : Learning Laravel
@m.reza6920 6 ماه پیش آپدیت شد
0

سلام
خیلی ممنون از @salar.mohammad2013 و @hosseinradvictor عزیز
واقعیتش اگر بخوام اینطوری رفتار کنم با کد، دقیقا چجوری میشه؟
من توی UserController و متد update، میخوام کاری کنم که کاربر رو از روی accesstoken خونده باشه، که جوری باشه که نتونه ایدی یه نفر دیگه رو بفرسته.

خلاصه، چیزی که توی ذهن منه اینطوری میشه:
(میدونم این چیزی که نوشتم وجود نداره)

public function update(UpdateUserRequest $request)
    {
        try {
            $token = $request->bearerToken();

            // i think about something like this:
            $userId = $token->user()->id;
            $user = User::findOrFail($userId);

            //or
            $user = $token->user();

            $user->update($request->only("name", "email"));

            return response()->json([
                'message' => 'your information updated successfully',
                'user' => new UserResource($user),
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'errors' => $e->getMessage()
            ], 500);
        }
    }

یعنی من نیاز دارم که ایدی کاربر یا خودش رو از روی توکن بگیرم و بعد عملیات مورد نظرم رو انجام بدم.


محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 6 ماه پیش مطرح شد
0

سلام
پاسخ سوال شما در این لینک هست

$token = PersonalAccessToken::where('token', $hashedToken)->first();
$user = $token->tokenable;

محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 6 ماه پیش آپدیت شد
1

و چیزی که مهمه و باید بدونی اینه که توکن هش شده توی دیتابیس و به شکل زیر باید عمل کنی
طبق این لینک تست کردم و جواب گرفتم

    public static function findToken($token)
    {
        if (strpos($token, '|') === false) {
            return static::where('token', hash('sha256', $token))->first();
        }

        [$id, $token] = explode('|', $token, 2);

        if ($instance = static::find($id)) {
            return hash_equals($instance->token, hash('sha256', $token)) ? $instance : null;
        }
    }

طبق این کد میفهمیم که اون پایپ یا علامت | رو باید از توکن حذف کرد و بعد اون به صورت هش شده دنبالش بگردیم کد زیر بهت یوزر رو از روی توکن میده

        $cookieWithPipe=$request->cookie('your_token_cookie_name');
        [$id, $tokenWithoutPipe] = explode('|', $cookieWithPipe, 2);
        $token = \Laravel\Sanctum\PersonalAccessToken::where('token', hash('sha256', $tokenWithoutPipe))->first();
        $user = $token->tokenable;
        return $user;

حسین افتخارراد
تخصص : نال کد
@hosseinradvictor 6 ماه پیش مطرح شد
0

راستش خیلی وقته با توکن ها کار نکردم ولی تا اونجا که خاطرم هست سه تا جدول وجود دارد یکی جدول یوزر و جدول توکن ها و جدول میانی بهتر هست درون phpmyadmin ویو دیاگرام بگیرید تا روابط جداول نمایش داده بشه شما از طریق جدول میانی میتونید یوزر و توکن رو پیدا کنید


محمدرضا فلکی
تخصص : Learning Laravel
@m.reza6920 6 ماه پیش آپدیت شد
-1

سلام @salar.mohammad2013
خیلی ممنون
به چندتا چیز برخوردم:

1_اولش که تست کردم بخاطر Static ارور داد:
کد:

 public function update(UpdateUserRequest $request)
    {
        try {

            $token = $request->bearerToken();

            if (strpos($token, '|') === false) {
                return static::where('token', hash('sha256', $token))->first();
            }

            [$id, $token] = explode('|', $token, 2);

            if ($instance = static::find($id)) {
                return hash_equals($instance->token, hash('sha256', $token)) ? $instance : null;
            }

            $cookieWithPipe = $request->cookie('your_token_cookie_name');
            [$id, $tokenWithoutPipe] = explode('|', $cookieWithPipe, 2);
            $token = \Laravel\Sanctum\PersonalAccessToken::where('token', hash('sha256', $tokenWithoutPipe))->first();
            $user = $token->tokenable;

            $user->update($request->only("name", "email"));

            return response()->json([
                'message' => 'your information updated successfully',
                'user' => new UserResource($user),
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'errors' => $e->getMessage()
            ], 500);
        }
    }

ارور: "errors": "Method App\Http\Controllers\Api\UserController::find does not exist."

2_بعدش کد رو تغییر دادم:

public function update(UpdateUserRequest $request)
    {
        try {

            $token = $request->bearerToken();

            if (strpos($token, '|') === false) {
                return \Laravel\Sanctum\PersonalAccessToken::where('token', hash('sha256', $token))->first();
            }

            [$id, $token] = explode('|', $token, 2);

            if ($instance = \Laravel\Sanctum\PersonalAccessToken::find($id)) {
                return hash_equals($instance->token, hash('sha256', $token)) ? $instance : null;
            }

            $cookieWithPipe = $request->cookie('your_token_cookie_name');
            [$id, $tokenWithoutPipe] = explode('|', $cookieWithPipe, 2);
            $token = \Laravel\Sanctum\PersonalAccessToken::where('token', hash('sha256', $tokenWithoutPipe))->first();
            $user = $token->tokenable;

            $user->update($request->only("name", "email"));

            return response()->json([
                'message' => 'your information updated successfully',
                'user' => new UserResource($user),
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'errors' => $e->getMessage()
            ], 500);
        }
    }

و وقتی از (user$)dd استفاده کردم خروجی زیر رو گرفتم:

{
    "id": 2,
    "tokenable_type": "App\\Models\\User",
    "tokenable_id": 10,
    "name": "api-token",
    "abilities": [
        "*"
    ],
    "last_used_at": "2023-10-29T13:12:48.000000Z",
    "expires_at": null,
    "created_at": "2023-10-26T13:22:40.000000Z",
    "updated_at": "2023-10-29T13:12:48.000000Z"
}

3_البته نمیدونستم چه چیزی رو باید توی cookie بنویسم ولی خروجی در رابطه با توکن بود


محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 6 ماه پیش مطرح شد
0

داداش گلم قطعه کد اول برای کمک گرفتن بود که گفتم از روش فهمیدم هم هش شده هم پایپ باید حذف بشه
قطه کد دوم کل چیزی بود ک شما نیاز داری و فقط همون و باید استفاده کنی

        $cookieWithPipe=$request->cookie('your_token_cookie_name');
        [$id, $tokenWithoutPipe] = explode('|', $cookieWithPipe, 2);
        $token = \Laravel\Sanctum\PersonalAccessToken::where('token', hash('sha256', $tokenWithoutPipe))->first();
        $user = $token->tokenable;
        return $user;

شما سوالتون اینه که من توکنی دارم و میخوام از روی توکن کاربر خودم رو پیدا کنم
توکن من توی پروژم از کوکی ها خونده میشه (میدلوری دارم که کوکی رو میزاره توی هدر که کاری به اینجاش نداریم)
در کل خط اول کد من توکن هست همین

$cookieWithPipe=$request->cookie('your_token_cookie_name');

من نوشتم your_token_cookie_name یعنی بیا اسم کوکی خودتو بنویس که توکن توشه
برای شما انگاری توی $token = $request->bearerToken() هست کوکی پس اصلا نیاز به خط اول کد من نداری
توکن خودت رو dd بگیر همین اول اول ببین آیا پایپ داره ؟ ( | ) همین علامتی که توی پرانتر هست منظورمه
اگر داره مثل خط زیر اگر بود خروجی شما

17|mNymifftkRZkGwAw4KkrWIVAmgadUOhsnDylqnBff7a4a755

یعنی نیاز هست که از اون بخش explode استفاده کنی تا جداش کنی و عدد قبلشم حذف کنی اگر نبود خب نیازی بهش نداری

[$id, $tokenWithoutPipe] = explode('|', $cookieWithPipe, 2);

حالا تا اینجا فقط ما توکن رو فقط گرفتیم و هیچ کار خاصی نکردیم اصلا
جدول توکن های ایجاد شده چون رمزنگاری شده و هش شده ما هم میاییم این توکن رو هش میکنیم و فقط به همین رکورد از جدول میرسیم

$token = \Laravel\Sanctum\PersonalAccessToken::where('token', hash('sha256', $tokenWithoutPipe))->first();

حالا این کالکشن دریافتی از مدل personalAccessToken به ما کاربر رو میده

$user = $token->tokenable;

تموم
کد من دقیقا اینه

    public function user(Request $request)
    {
        $cookieWithPipe=$request->cookie('board_info_login_token');
        [$id, $tokenWithoutPipe] = explode('|', $cookieWithPipe, 2);
        $token = \Laravel\Sanctum\PersonalAccessToken::where('token', hash('sha256', $tokenWithoutPipe))->first();
        $user = $token->tokenable;
        return $user;
    }

و خروجی اون یوزر منه که میبینی در زیر

{
    "id": 2500,
    "fullName": "\u0634\u0631\u06a9\u062a \u0627\u0646\u0641\u0648\u0631\u0645\u0627\u062a\u06cc\u06a9 \u0633\u067e\u0646\u062a\u0627",
    "username": "sepanta",
    "email_verified_at": null,
    "mobileNumber": null,
    "is_professor": 0,
    "created_at": null,
    "updated_at": null
}

هیچ کد اضافی نداره
مشکل شما در کد ، توکنته
باید توکن رو پیدا کنی توی کد خودت که کجا داری میفرستی و به چه شکل داری ازش استفاده میکنی همین
طبق کدی که من از شما میبینم کد زیر باید برات مناسب باشه

        $cookieWithPipe=$request->bearerToken();
        [$id, $tokenWithoutPipe] = explode('|', $cookieWithPipe, 2);
        $token = \Laravel\Sanctum\PersonalAccessToken::where('token', hash('sha256', $tokenWithoutPipe))->first();
        $user = $token->tokenable;
        return $user;

ولی شما نیاز داری که مقدار $request->bearerToken(); رو خروجی بگیری و مطمین بشی که توکن توش هست و با پایپ هست تا کد بالا کار کنه
اگر نبود باید مرحله جدا سازی عدد و پاپ رو هم فاکتور بگیری

برای من توکن توی کوکی هست و توسط میدلور میام میزارمش توی هدر درخواستم دلیلشم اینه که از کوکی با نوع httpOnly دارم استفاده میکنم که درخواستم امن باشه و توکن قابل مشاهده نباشه توسط مرور گر


محمدرضا فلکی
تخصص : Learning Laravel
@m.reza6920 6 ماه پیش مطرح شد
1

خیلی خیلی ممنونم @salar.mohammad2013 عزیز
کار کرد و جواب داد 🌹


برای ارسال پاسخ لازم است وارد شده یا ثبت‌نام کنید

ورود یا ثبت‌نام