6 پاسخ

پیاده سازیauthentication چند موردی در لاراول

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


ثبت پرسش جدید
میکائیل
تخصص : برنامه نویسی سمت سرور و کلاینت
@FullStack 1 سال پیش آپدیت شد
0

خوب ورود هم خیلی اسونه توی صفحه لاگین یه دکمه بزار برای ورود با شماره تلفن بعد توی صفحه لاگین با شماره یه اینپوت میزاریکه کاربر شمارشو وارد کنه وقتی وارد کرد و تایید رو زد اول چک کنه ببینه یوزری با این شماره داخل دیتابیس وجود دارد یا نه اگه وجود نداشت که اررور بهش بر گردونه و بگه شماره مورد نظر وجود ندارد یا اشتباه است اما اگه وجود داشت یه کد ارسال کنه به شماره و بره به صفحه وارد کردن کد و شماره رو هم به صورت session بفرسته وقتی کد رو وارد کرد چک کنه که کدی وارد کرده با کدی که توی دیتابیس وارد شده مطابقت داره با این کد و یوزر یا نه اگه نداشت به صفحه قبل برگرده یا حالا تو همون صفحه یه اررور بهش نشون بده که کد وارد شده نامعتبره اگه معتبر بود کد پاک بشه و بیاد اطلاعات یوزر رو بر اساس شماره کاربر برگردونه بعد کاربر رو با دستور auth()->loginUsingId(); بیاد با ایدی یوزری که برگردونده لاگین کنه و ریدایرکت کنه به صفحه home و اگه کد هاشم بخوای چون ارسال پیامک سرویسو اینا میخواد فقط میتونم مراحلی که گفتمو برات کداشو بزارم بدون ارسال پیامک به شماره و فقط کد توی دیتابیس ذخیره میشه ولی ارسال پیامک رو خوتد خیلی راحت میتونی انجام بدی

اول اینکه باید یک جدول برای کد ها ایجاد کنی که ایدی یوزر و کد و تاریخ منقضی شدن کد رو بگیره مثلا اسم جدولش باشه code

خوب وقتی کاربر شماره رو وارد کرد و تایید رو زد هدایت میشه به کنترولر و توی اونجا به اینصورت میشه

public function login(Request $request)
    {
        $data = $request->validate([
            'phone' => 'required|exists:users,phone_number'
        ],[
            'phone' => ['required' => 'شماره نمیتواند خالی باشد','exists' => 'شماره وارد شده یافت نشد']
        ]);

        $user = User::where('phone_number',$request->phone)->first();

        // Generate And Send Code
        $code = Code::where('user_id',$user->id)->first();
        $randcode = rand(10000,99999);

        if ($code){
            $code->update([
                'code' => $randcode,
                'expired_at' => now()->addHours(3)
            ]);
        }else {
            Code::create([
                'user_id' => $user->id,
                'code' => $randcode,
                'expired_at' => now()->addHours(3)
            ]);
        }

        // Send Sms To Number

        // Save User Number in session
        $request->session()->flash('phone',$data['phone']);

        // Redirect To Verify Code Route
        return redirect(route('auth.code_verify'));

    }

بعدش میره توی روت چک کردن کد اونجا یه اینپوت دیگه باید بزاری که کاربر کدی که ارسال شده به شمارش رو وارد کنه کنترولرش هم به این صورت میشه

public function code_verify(Request $request)
    {
        $data = $request->validate([
            'code' => 'required'
        ],[
            'code' => ['required' => 'لطفا کد ارسالی را وارد نمایید']
        ]);

        if (!$request->session()->has('phone')){
            return redirect(route('auth.login'));
        }

        $user = User::where('phone_number',$request->session()->get('phone'))->first();

        $status = Code::where('user_id',$user->id,'code',$data['code'])->first();

        if ($status){
            if($status->expired_at >= now()){
                auth()->loginUsingId($user->id);
                $status->delete();
                return redirect(route('home'));
            }else {
                return redirect(route('auth.login'))->withError('code','کد وارد شده منقضی شده است');
            }
        }else {
            return redirect(route('auth.login'))->withError('code','کد وارد شده اشتباه است');
        }
    }

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


میکائیل
تخصص : برنامه نویسی سمت سرور و کلاینت
@FullStack 1 سال پیش آپدیت شد
0

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

auth()->loginUsingid($id);

بیاد و کاربر رو لاگین بکنه واسه گوگل هم باید وارد سایت گوگل دولوپر بشیده و OAuth واسه خودتون کلید و سکریت کی بگیرید و تو پروژه استفاده کنید هر کدوم از این مباحثی که برای ورود گفتید خودش یه بحث جدا داره و نمیشه همشو اینجا توضیح داد

اما اگه نظر منو میخوای یه ثبت نام با email و password بزار یا ورود با جیمیل و کاربر موقعه ثبت نام باید شمارشو وارد و تایید بکنه و یه لینکی زیر قسمت لاگین بزار که کاربر با استفاده از اون بتونه با شماره ای که موقعه ثبت نام با email وارد کرده وارد وبسایت بشه


امیرحسین زارعیان
تخصص : مدیر عامل ،برنامه نویس ،استرات...
@amirzareian 1 سال پیش مطرح شد
0

@FullStack مرسی که راهنمایی کردی در واقع چیزی که می خوام اینه که این وبسایت من چند حالت ورود و عضویت داشته باشه که کاربر آزادانه انتخاب کنه . حالا چرا ؟
چون که من خیلی وقتا راحتم که سریع با گوگل ورود کنم و بعدا پروفایلم رو کامل کنم حالا اگر خواستم بعدا با OTP وارد شم و یا نه اول با شماره تلفتن و OTP بعدش اگر خواستم بتونم با ایمیل هم وارد شم و ...
حالا اگر بتونی شما کامل کمکم کنی خیلی ممنونتون میشم.


میکائیل
تخصص : برنامه نویسی سمت سرور و کلاینت
@FullStack 1 سال پیش آپدیت شد
0

خوب اگه اینجوری باشه که کارتون خیلی آسونه ببینید من فرض رو بر این میگیریم که شما مثلا ثبت نام با email و password رو پیاده سازی کردید و میخواید کاربر با استفاده از حساب گوگل وارد بشه خوب چیکار میکنید اول اینکه توی بخش ورود و ثبت نام یه دکمه اضافه میکنید به اسم ورود با گوگل خوب وقتی کاربر روی دکمه کلیک کنه خوب الان میخوام طبق خود مستندال لاراول بهت بگم چطوری انجامش بدی اول باید پکیج

composer require laravel/socialite

رو توی لاراول نصب کنی بعد باید وارد سایت
https://console.cloud.google.com/apis/credentials/
میشی اول وارد حساب گوگل میشی و ایران رو هم تحریم کرده باید تحریم شکن بزنی خوب بعد که وارد شدی میری تو قسمت Credentials میری و گزینه Create Credentials رو انتخاب میکنی و گزینه OAuth Client Id رو انتخاب میکنی یه سری اطلاعات ازت میخواد که اونارو بخوام بگم خیلی متن طولانی میشه خودت بخونی متوجه میشی کدوم چطور وارد کنی فقط حواست باشه گزینه اولی رو Web Application انتخاب کنی چون برای وبسایت میخوای و اینکه حواست باشه که توی Authorized redirect URIs یه ادرس اضافه کنی که اطلاعات اون یوزر رو اونجا بفرته و حتما باید اون ادرس رو توی پروژت مشخص کنی به صورت callback اطلاعات رو اونجا بر میگردونه ووقتی همه رو انجام دادی اخر سر دوتا کلید بهت میده به اسم client id و client secret اینارو کپی کنی و توی .env پروژت با اسم های مشخص ذخیره کن وقتی این کار رو کردی بقیش خیلی آسون میشه وارد config/services.php میشی و این کد رو اضافه میکنی

'google' => [
    'client_id' => env('GOOGLE_CLIENT_ID'),
    'client_secret' => env('GOOGLE_CLIENT_SECRET'),
    'redirect' => 'http://example.com/callback-url',
],

دیگه معلومه اون client id و client secret رو که توی env ذخیره کردی رو پاس میدی بهش و redirect رو حواست باشه باید یا مستقیم بهش بدی یا اون رو هم توی .env ذخیره کنی و بهش بدی این همون ادرسی هست که توی اکانت گوگل داده که اطلاعات یوزر رو به صورت callback بفرسته پس اینو حواست باشه اشتباه وارد نکنی چون دیگه اطلاعات رو درست دریافت نمیکنی بعد از اینکه کاربر اکانتشو انتخاب کرد میفرسته خوب تا اینجا این باشه

بعد دوتا روت تعریف میکنی یکی واسه اینکه اکانت های جیمیل کاربر رو نشون بده که بتونه انتخاب کنه یکی هم واسه اینکه بعد از اینکه انتخاب کرد اطلاعاتش رو اونجا چک بکنی ببینی که وجود داره یا نه اگه نداره اکانتشو بسازه اگه وجود داره کاربر لاگین بشه که میتونی به صورت get تعریف کنی و اسم هاشون رو میتونی gooogle/auth و google/callback بزاری

وقتی کاربر روی دکمه ورود با گوگل رو زد به روت بالا بره یعنی google/auth توی فانکشن این روت باید به این صورت تعریف کنی

return Socialite::driver('google')->redirect();

خوب توی این روت تموم میشه میاد ویوی جیمیل های کاربر رو نشون میده وقتی کاربر یکی از جیمیل هارو انتخاب کنه اون موقعه میاد به سمت روت google/callback توی این روت باید اینو تعریف کنی


try {  
$google = Socialite::driver('google')->user();

    $user = User::where('email',$google->email)->first();

    if ($user){
        // login user
        auth()->loginUsingId($user->id);
    }else{
        // create user
        $new = User::create([
            'name' => $google->name,
            'email' => $google->email,
            'password' => Hash::make(Str::random(10))
        ]);

        auth()->loginUsingId($new->id);
    }

    return redirect('home');
}catch (Exception $exception){
    // show exception
}

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


امیرحسین زارعیان
تخصص : مدیر عامل ،برنامه نویس ،استرات...
@amirzareian 1 سال پیش مطرح شد
0

@FullStack مرسی واقعا توی این مرحله خیلی کمک کردی شما ممنونم .
حالا برای OTP و شماره موبایل چطور ؟ اگر ورود با اس ام اس رو هم بهم بتونی به این خوبی توضیح بدی بینظیر میشه مرسی واقعا .


میکائیل
تخصص : برنامه نویسی سمت سرور و کلاینت
@FullStack 1 سال پیش آپدیت شد
0

خوب ورود هم خیلی اسونه توی صفحه لاگین یه دکمه بزار برای ورود با شماره تلفن بعد توی صفحه لاگین با شماره یه اینپوت میزاریکه کاربر شمارشو وارد کنه وقتی وارد کرد و تایید رو زد اول چک کنه ببینه یوزری با این شماره داخل دیتابیس وجود دارد یا نه اگه وجود نداشت که اررور بهش بر گردونه و بگه شماره مورد نظر وجود ندارد یا اشتباه است اما اگه وجود داشت یه کد ارسال کنه به شماره و بره به صفحه وارد کردن کد و شماره رو هم به صورت session بفرسته وقتی کد رو وارد کرد چک کنه که کدی وارد کرده با کدی که توی دیتابیس وارد شده مطابقت داره با این کد و یوزر یا نه اگه نداشت به صفحه قبل برگرده یا حالا تو همون صفحه یه اررور بهش نشون بده که کد وارد شده نامعتبره اگه معتبر بود کد پاک بشه و بیاد اطلاعات یوزر رو بر اساس شماره کاربر برگردونه بعد کاربر رو با دستور auth()->loginUsingId(); بیاد با ایدی یوزری که برگردونده لاگین کنه و ریدایرکت کنه به صفحه home و اگه کد هاشم بخوای چون ارسال پیامک سرویسو اینا میخواد فقط میتونم مراحلی که گفتمو برات کداشو بزارم بدون ارسال پیامک به شماره و فقط کد توی دیتابیس ذخیره میشه ولی ارسال پیامک رو خوتد خیلی راحت میتونی انجام بدی

اول اینکه باید یک جدول برای کد ها ایجاد کنی که ایدی یوزر و کد و تاریخ منقضی شدن کد رو بگیره مثلا اسم جدولش باشه code

خوب وقتی کاربر شماره رو وارد کرد و تایید رو زد هدایت میشه به کنترولر و توی اونجا به اینصورت میشه

public function login(Request $request)
    {
        $data = $request->validate([
            'phone' => 'required|exists:users,phone_number'
        ],[
            'phone' => ['required' => 'شماره نمیتواند خالی باشد','exists' => 'شماره وارد شده یافت نشد']
        ]);

        $user = User::where('phone_number',$request->phone)->first();

        // Generate And Send Code
        $code = Code::where('user_id',$user->id)->first();
        $randcode = rand(10000,99999);

        if ($code){
            $code->update([
                'code' => $randcode,
                'expired_at' => now()->addHours(3)
            ]);
        }else {
            Code::create([
                'user_id' => $user->id,
                'code' => $randcode,
                'expired_at' => now()->addHours(3)
            ]);
        }

        // Send Sms To Number

        // Save User Number in session
        $request->session()->flash('phone',$data['phone']);

        // Redirect To Verify Code Route
        return redirect(route('auth.code_verify'));

    }

بعدش میره توی روت چک کردن کد اونجا یه اینپوت دیگه باید بزاری که کاربر کدی که ارسال شده به شمارش رو وارد کنه کنترولرش هم به این صورت میشه

public function code_verify(Request $request)
    {
        $data = $request->validate([
            'code' => 'required'
        ],[
            'code' => ['required' => 'لطفا کد ارسالی را وارد نمایید']
        ]);

        if (!$request->session()->has('phone')){
            return redirect(route('auth.login'));
        }

        $user = User::where('phone_number',$request->session()->get('phone'))->first();

        $status = Code::where('user_id',$user->id,'code',$data['code'])->first();

        if ($status){
            if($status->expired_at >= now()){
                auth()->loginUsingId($user->id);
                $status->delete();
                return redirect(route('home'));
            }else {
                return redirect(route('auth.login'))->withError('code','کد وارد شده منقضی شده است');
            }
        }else {
            return redirect(route('auth.login'))->withError('code','کد وارد شده اشتباه است');
        }
    }

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


امیرحسین زارعیان
تخصص : مدیر عامل ،برنامه نویس ،استرات...
@amirzareian 1 سال پیش مطرح شد
1

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


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

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