بررسی احراز هویت کاربران در فریم ورک لاراول 8

مقدمه :همانطور که میدونید در نحوه اجرای احراز هویت کاربران "Authentication" در فریم ورک لاراول آقای تیلور اوتول و تیم لاراول هر چند وقت یکبار با یک سری پیکج جدید تغییرات اساسی اعمال می کنند! مثلا پکیج های قدیمی مثل لاراول UI یا جدیدا جت استریم، فورتیفای، "breeze". حالا درکنار این پکیج ها هم میان درخواست نصب پکیج های دیگه ای مثل Livewire یا inertia برای ارسال رگوئست های آژاکسی به سرور رو میدن و فریم ورک هایی مثل Tailwind css رو هم برای استایل دهی ویو هاشون رو میخوان که نصب بشه.این پکیج ها امکانات زیادی دارند مثلا همین جت استریم یه صفحه پروفایل کاربری کامل ایجاد میکنه از تایید دومرحله ای تا حتی تا تشخیص دستگاه های دیگه ای که باهاشون احراز هویت شدین رو بهتون تو پروفایل کاربری نشون میده تا اگه به سیستمی دیگه دسترسی ندارین یا رمز رو تغییر دادین تو سیستم خودتون لاگین بمونید و از سایر دیوایس ها خارج بشید، مثل همون امکاناتی که سایت های بزرگ مثلا گوگل و... دارن که از نظر من خیلی باحال و کاربردی هم هست که البته دستی هم میشه خودمون اضافه کنیم! درسته که بسیاری از امکانات رو به بهترین و حرفه ای ترین شکل ممکن به هسته فریم ورک اضافه می کنند اما من به شخصه ترجیح میدم متناسب نیازم سر هر پروژه لاراول رو شلوغ نکنم! مخصوصا اینکه بعضی وقت ها نیاز داریم کامل این بخش رو بازنویسی کنیم مثلا احراز هویت رو ببریم روی OTP ها و از ایمیل بریم روی شماره موبایل کاربر که در روشی که خدمتان عرض میکنم اعمال تغییرات توی سیستم احراز هویت واضح تر هست.لیست مطالبی که تو این مقاله گفته شده:ساخت پروژه جدید لاراول 8ساخت دستی بخش ثبت نامساخت دستی بخش ورودنحوه تشخیص کاربران مسدود شدهساخت بخش "مرا به خاطر بسپار" هنگام ورودسیستم ارسال تایید ایمیل کاربرسیستم بازیابی رمز عبورفارسی سازی پیغام ها و ایمیل هاایجاد پروژه جدید:توی قدم اول اگه installer لاراول در کامپوزر رو هنوز نصب نکردید با وارد کردن دستور زیر در خط فرمان می تونید نصبش کنید:composer global require laravel/installerو بعد از پایان نصب این اینستالر تنها کافیه با دستور زیر یک پروژه جدید لاراول رو ایجاد کنیم که به جای "your_app_name" باید اسم پروژه خودتون رو بنویسید:laravel new your_app_nameدر فایل env موجود در پروژه، اطلاعات پایگاه داده خودتون رو وارد کنید تا به دیتابیس متصل بشیم و الان دیگه همه چیز آماده است همانطور که می بینید مایگریشن جدول کاربران یا همون Users هم آماده اجرا کردنه که کافیه با کد زیر مایگریشن ها رو اجرا کنید:php artisan migrateاگر خطا گرفتید که حتما میگیرید :) باید کد زیر رو برای تعیین مقدار پیشفرض رشته ها در AppServiceProvider.php و در فانکشن boot وارد کنیم: Schema::defaultStringLength(191);و همچنین بالای این پرونده، Facade زیر رو هم فراموش نکنید use کنید:use Illuminate\Support\Facades\Schema;خب حالا دوباره عمل مایگریت رو انجام بدید تا بریم سراغ ادامه کار.ساخت کنترلر هاتا اینجا همش درباره راه اندازی لاراول بود اصل کار ما تازه شروع میشه. اول باید کنترلر های مورد نیازمون رو بسازیم که من عموما در پوشه Controllers\Auth سه تا کنترلر برای بخش احراز هویت می سازم یکی به اسم authController که جنبه عمومی داره و کد های مربوط به نمایش ویو ها و خروج از حساب رو توش می نویسم و دوتا کنترلر دیگه به اسم های loginController و registerController که از اسم هاشون مشخصه برای عملیات ورود و ثبت نام از اینها استفاده میکنم که خب شما میتونید کلا از یکی فقط استفاده کنید ولی پیشنهاد میدم آینده نگر باشید و همه چیز رو دسته بندی کنید تا وقتی پروژه بزرگ شد توی کد های خودتون گم نشید! با دستورات زیر هر سه کنترلر رو به ترتیب میسازیمphp artisan make:controller Auth\authController php artisan make:controller Auth\loginControllerphp artisan make:controller Auth\registerController روت ها حالا وقتشه روت ها و ویو های مربوط به عمل احراز هویت رو بسازیم مثل login و register و logout همچنین ساخت بخش ویو ها رو فاکتور میگیرم که خارج از بحث ماست! اما برای روت ها، بالای صفحه باید کنترلر هامون رو use کنیم و روت ها رو با توجه به کنترلر و فانکشن های مربوط به خودشون تعریف کنیم:<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\Auth\authController; use App\Http\Controllers\Auth\loginController; use App\Http\Controllers\Auth\registerController; Route::get('/', [authController::class, 'loginView'])->name('index'); //روت نمایش صفحه اصلی که ارجاع دادم به صفحه ورود Route::get('/login', [authController::class, 'loginView'])->name('login'); //روت نمایش ویو صفحه ورود Route::get('/register', [authController::class, 'registerView'])->name('register'); //روت نمایش ویو صفحه ثبت نام Route::get('/logout', [authController::class, 'logout'])->name('logout'); //روت خروج از حساب Route::post('/login', [loginController::class, 'login']); //روت پست اطلاعات فرم ورود Route::post('/register', [registerController::class, 'register']); //روت پست اطلاعات فرم ثبت نام Route::prefix('dashboard')->middleware(['auth'])->group(function () { //گروه روت های داشبورد که با میدلور خود لاراول جلوی ورود کاربر وارد نشده رو گرفتم Route::get('/', function () { }); });کنار هر خط کد بالا کامنت گذاشتم که ابهامی نمونه بعد از تعریف روت ها کافیه در کنترلر های مربوطه و فانکشن مورد نظر روت هامون، کد های خودمون رو بنویسیم. ثبت نام کاربر جدیدبرای ثبت نام کاربر جدید کار بسیار ساده هست تنها کافیه از الکوئنت کمک بگیریم و یک رکورد جدید در دیتابیس ثبت کنیم که میشه همون کاربرمون، پس در کنترلر registerController و در فانکش register اش که داده هامون از ویو بهش post شده است رو میگیرم و بعد از اعتبار سنجی به پایگاه داده اضافه می کنیم:public function register(Request $request) //رگوئست ارسالی کاربر از صفحه ثبت نام رو دریافت می کنیم { $validated = $request->validate([ //داده ها را اعتبار سنجی می کنیم 'email' => 'required|email|unique:users|max:255', 'password' => 'required|max:255|min:6', ]); $user = new User(); //یک شی جدید از روی مدل یوزر میسازیم $user->password = Hash::make($request->password); //پسورد را ابتدا با روش بی کریپت هش میکنیم $user->email = $request->email; //ایمیل ارسالی را دریافت می کنیم $user->save(); //اطلاعات را پایگاه داده ثبت می کنیم return redirect()->intended('index'); //کاربر را به صفحه مورد نظر هدایت میکنیم }کنار تمام کد های بالا هم کامنت گذاشتم که ابهامی نباشه. تا اینجا تونستیم یک کاربر جدید رو ثبت کنیم البته آخرش هم میتونیم یک سشن برای پیغام ثبت نام موفقیت آمیز یا حتی عملیات ارسال ایمیل تایید به کاربر رو انجام بدیم.احراز هویت و ورود به سیستمبرای بخش اصلی کار یعنی احراز هویت و ورود به سیستم بعد از اینکه کاربران توی بخش ویو اطلاعاتشون مثل ایمیل و پسورد رو وارد کردن و داده ها به کنترلر پست شد طبق روال بالا در کنترلر loginController و فانکشن login کد های زیر رو وارد می کنیم :use Illuminate\Support\Facades\Auth; //یوز کردن فساد احراز هویت رو بالای پرونده فراموش نکنید public function login(Request $request) //دریافت رگوئست ارسالی کاربر در صفحه ورود { $validated = $request->validate([ //داده ها رو اعتبار سنجی میکنیم 'email' => 'required|email', 'password' => 'required', ]); $credentials = $request->only('email', 'password'); //فیلد های مورد نظر رو داخل متغیر میریزیم if (Auth::attempt($credentials)) { //اگر کاربری با مشخصات داده شده موجود باشد نتیجه صحیح باز میگردد $request->session()->regenerate(); //سشن را بازسازی می کنیم return redirect()->intended('dashboard'); //کاربر احراز هویت شده را با داشبورد منتقل می کنیم } return back()->withErrors([ //کاربر پیدا نشد و هنگام بازگشت به صفحه ورود خطا را نشان میدهیم 'email' => 'کاربری با این مشخصات وجود ندارد', ]); } کنار کدهای بالا هم کامنت گذاشتم اما لازمه یه توضیح مختصر برای بعضی از دستورات بدم. اول دستور زیر که در کد بالا کار اصلی رو انجام میده :$credentials = $request->only('email', 'password');اینجا دوتا ورودی از ما گرفته، اول ایمیل کاربر که در بعضی موارد، ما میتونیم بجای ایمیل از نام کاربری یا موبایل برای احراز هویت کاربران استفاده کنیم، و دوم پسورد کاربر! بجای این دستور میتونیم از همان متغیر ولیدیشن validated که بالا نوشتیم استفاده کنیم اما به این دلیل که این دستور قابل توسعه است و میتونه ورودی های بیشتری بگیره که در ادامه مقاله خواهم گفت اینکار رو کردیم که قاطی نشه.نکته مهم:پسورد توی دستور بالا خودش هش و ارسال میشه پس نباید شما خودتون دستی اون رو هش کنید و بعد ارسال کنید. اگه اینکار رو بکنید پسورد هش شده دوباره هش میشه و کلا یه رشته دیگه تحویل میده که طبیعتا با پسورد ذخیره شده در دیتابیس متفاوت خواهد بود و هیچ کاربری نمیتونه دیگه لاگین کنه :)مورد بعدی دستور زیره که کوئری اصلی رو برای دیتابیس میسازه و نتیجه احراز هویت رو برمیگردونه :Auth::attempt($credentials)کد بالا هم یک ورودی گرفته که داخل اون متغیری با دو پارامتر ایمیل و پسورد کاربر که قبلا به صورت آرایه توش ریخته بودیم رو برای ساخت کوئری ارسال میکنه. اگه کاربری با این رمز و ایمیل پیدا بشه خروجی این دستور True هست که ما ازش استفاده کردیم برای تکمیل احراز هویت کاربرمون.بعد از اینکه کاربر اطلاعاتش درست بود اولین دستوری که بعد از عملیات احراز نوشتیم دستور زیر بود :$request->session()->regenerate();این دستور میاد و یک سشن آی دی جدید برای کاربرمون میسازه تا از خطر Session fixation جلوگیری بشه!البته توی دستورات بخش ورود به سایت ما میتونیم بجای دستور زیر که بالا نوشته بودیم:$credentials = $request->only('email', 'password');یکباره از همون دستورات مربوط به validate رگوئست ارسالی هم استفاده کنیم مثلا :$credentials = $request->validate([ 'email' => ['required', 'email'], 'password' => ['required'], ]);که از همون اول ایمیل و پسورد رو داخل متغیر credentials گذاشتیم و بعد هم که در بخش Auth::attempt میره برای چک شدن اطلاعات، اما من پیشنهاد نمیدم چون با روش قبلی که نوشته بودیم همانطور که در ادامه توضیح میدم امکانات جالبی در انتظارمونه.اگر بخواییم بجز ایمیل و پسورد موارد دیگری رو هم بررسی کنیم چی؟یه نکته جالب اینجا هست که مثلا شاید جدول کاربران شما بخوایید شامل یه فیلد باشه برای امکان مسدود کردن یک کاربر و شما نخوایید کاربر مسدود شده حتی با صحیح بودن رمز و ایمیل هم بتونه به سایت ورود کنه! اینجا میتونیم بجای این دستور زیر که بالا توی کد اصلیمون استفاده کرده بودیم:$credentials = $request->only('email', 'password'); از این دستور زیر توی همون بخش Auth::attempt استفاده کنیم :if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) { // کاربر احراز هویت شده و ادامه دستورات }که همانطوری که میبینید در یک آرایه ابتدا ایمیل و بعد پسورد و در آخر گزینه active رو قرار دادیم که اگه کاربرمون فعال بود و ستون active این کاربر برابر True یا 1 بود عملیات ورود انجام بشه یا به اصطلاح کاربرمون احراز هویتش کامل بشه. که اینجا active مثاله شما میتونید هرچیزی که لازم دارید رو بزارید.چطوری بخش "مرا به خاطر بسپار" رو ایجاد کنیم؟حتما توی خیلی از سایت ها این قابلیت رو دیدید و همچنین پکیج های احراز هویت خود لاراول هم این امکان رو راه اندازی می کنن! مثلا زمانی که کاربر تیک گزینه "مرا به خاطر بسپار" رو زده بود، تا وقتی که دکمه خروج رو نزده روی سیستم لاگین بمونه. برای اینکار اول لازمه که فیلد remember_token رو از جدول پیشفرض کاربران دیتابیس که با مایگریشن ها ایجاد شده رو حذف نکرده باشید. و بعد تنها کافیه در صورت نیاز به بخاطر سپرده شدن مقدار True رو به آرگومان دوم متد attempt پاس بدیم، مثل دستور زیر:if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) { // کاربر احراز هویت شده و تا خروج رو نزده باشد در این حالت می ماند }همانطور که در کد بالا مشخص هست در آرگومان دوم از متغیر remember استفاده کردم که در صورت True بودن مقدار این متغیر کاربر تا زدن دکمه خروج در این سیستم لاگین می ماند.خروج کاربر از سیستموقتی بخواییم کاربر از سیستم خارج بشه یا به اصطلاح عمل logout انجا بشه کافیه در کنترلر و فانکشن مربوط به روت logout خودمون از دستور زیر برای خروج از حساب کاربری استفاده کنیم :use Illuminate\Support\Facades\Auth; //یوز کردن فساد احراز رو فراموش نکنید public function logout(Request $request) { Auth::logout(); //باطل کردن احراز هویت فعلی $request->session()->invalidate(); //نامعتبر سازی سشن های فعلی $request->session()->regenerateToken(); //تولید مجدد توکن return redirect('/'); //ریدایرکت کاربر به صفحه اصلی }همانطوری که توی کامنت های کنار دستورات بالا مشخص کردم ابتدا با دستور Auth::logout احراز هویت فعلی کاربر رو باطل میکنیم که همین کار به تنهایی برای خروج کاربر از حساب کاربریش کافیه اما پیشنهاد میشه که حتما مطابق دستور خط بعدی سشن های فعلی رو نامعتبر کنیم و مجددا توکن رو برای امنیت بیشتر و جلوگیری از همزمانی ارسال دستورات مشابه، باز تولید کنیم.ارسال ایمیل تایید ثبت نامیکی از بخش های کاربردی هر سیستم احراز هویتی همین بخشه که بعد از ثبت نام کاربر جدید، یک ایمیل تایید برای کاربر ارسال بشه تا با کلیک روی لینک تایید آدرس ایمیلش تایید بشه و مطمئن بشیم کاربر ایمیل واقعی برای ثبت نام استفاده کرده و بات یا اسپم نیست.برای پیاده سازی این بخش اول باید یه سرویس ارسال کننده ایمیل برای پروژه تعریف کنیم. فعلا که تو مرحله توسعه هستیم من از میل ترپ برای سرویس ارسال کننده ایمیل هام استفاده می کنم شما بعدا میتونید از جیمیل یا سرور خودتون استفاده کنید. خب در ادامه تنظیماتش رو توی فایل env وارد میکنم، دریایی از آموزش برای این تنظیمات mailtrap در لاراول هست کاری هم نداره 30 ثانیه است :)اول باید مطمئن بشیم که کانترکت MustVerifyEmail در بالای مدل User فراخوانی شده باشه که پیشفرض هم همینطوره و البته MustVerifyEmail در کلاس کاربر مدلمون باید مطابق کد زیر implements هم بشه:use Illuminate\Contracts\Auth\MustVerifyEmail; class User extends Authenticatable implements MustVerifyEmail { use Notifiable; // ... }بعد از اینکار باید برگردیم به کنترلری که دستورات ثبت کاربر جدید رو توش نوشته بودیم (برای ما اینجا registerController است) و اول بالای کنترلر ایونت زیر رو فراخوانی کنیم:use Illuminate\Auth\Events\Registered;و دقیقا بعد از ذخیره کاربر جدید در دیتابیس با استفاده از دستور زیر ارسال ایمیل تایید رو که در هسته لاراول از قبل آماده هست رو هم انجام بدیم:event(new Registered($user));حتما توجه داشته باشید که فیلد پیشفرض email_verified_at در جدول کاربران رو پاک نکرده باشید! اگه پاک کردید دوباره بسازید. این فیلد تاریخ تایید ایمیل توسط کاربر رو ذخیره میکنه و میشه کلید اصلی اینکه کاربر ایمیلش رو تایید کرده یا نه.برای ادامه کار ما به 3 روت دیگه نیاز داریم، اول برای اینکه صفحه ای داشته باشیم تا در صورت لاگین کاربری که تایید ایمیل انجام نداده بود بفرستیمش اونجا و بهش این قضیه تایید ایمیل رو اطلاع بدیم.دوم روتی هست که برای هندل رگوئست دکمه تایید ایمیلی که به کاربر ایمیل شده لازمش داریم.و سوم روتی برای ارسال مجدد ایمیل تایید به کاربر، برای مواقعی که به هر دلیلی ایمیل بهش نرسیده.با استفاده از میدلور verified روت هایی که کاربر برای دسترسی بهشون نیاز داره تا اول تایید ایمیل رو انجام بده مشخص میکنیم. و بعد روت اولی که بالا گفتم رو مطابق زیر ایجاد میکنیم:Route::get('/email/verify', function () { return view('auth.verify-email'); })->middleware('auth')->name('verification.notice');دوستان توجه داشته باشید که اسم این روت حتما باید verification.notice باشه و این از پیش تعریف شده در هسته لاراول است. حتما هم به این روت میدلور auth رو بدید تا کاربرای مهمان نتونن این صفحه رو ببینند. الان وقتی کاربری ثبت نام کرده باشه و قبل از تایید ایمیل لاگین کنه به کمک میدلور verified تشخیص داده میشه و به این روت بالا ریدایرکت میشه.روت دوم مربوط به بخشی است که قراره کاربر بعد از کلیک روی لینک تایید توی ایمیل خودش اون رو باز کنه. این بخش میاد و عمل تایید ایمیل رو برامون انجام میده:use Illuminate\Foundation\Auth\EmailVerificationRequest; //فراموش نکنید بالای صفحه باید این فایل رو فراخونی کنید Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) { $request->fulfill(); return redirect('/home'); //صفحه ای که قراره بعد از تایید ایمیل بهش ریدایرکت بشه })->middleware(['auth', 'signed'])->name('verification.verify');روت بالا اسمش verification.verify هست که این هم از پیش تعریف شده و نباید عوض بشه. دو میدلور auth و signed هم به این روت نسبت داده شده تا جلوی ریگوئست های فیک گرفته بشه.میرسیم به روت سوم که برای ارسال مجدد لینک تایید به ایمیل ازش استفاده میشه :use Illuminate\Http\Request; Route::post('/email/verification-notification', function (Request $request) { $request->user()->sendEmailVerificationNotification(); return back()->with('message', 'لینک تایید مجددا ارسال شد'); })->middleware(['auth', 'throttle:6,1'])->name('verification.send');همانطور که میبینید این روت از نوع post هست با اسم از پیش تعریف شده verification.send و میدلور auth براش ست شده تا کاربری که قراره ایمیل براش ارسال بشه مشخص باشه. همچنین اینجا از میدلور throttle استفاده شده که باهاش میشه مشخص کرد کاربر مثلا در هر دقیقه چندبار بتونه این درخواست رو ارسال کنه تا فشار روی سرور نیاد و ریگوئست اسپم به سرور ارسال نشه.بازیابی رمز عبورلاراول برای بخش بازیابی رمز عبور به این صورت عمل میکنه که ابتدا کاربر درخواست خودش رو با وارد کردن ایمیلی که باهاش ثبت نام کرده رو به سیستم میده و بعد یک ایمیل هاوی لینک مخصوص به خودش رو دریافت میکنه که باهاش میتونه رمز عبور جدید رو تنظیم کنه.برای اینکار ابتدا در بالای مدل User خودمون کانترکت و نوتفیکشن زیر باید use شده باشه :use Illuminate\Contracts\Auth\CanResetPassword; use Illuminate\Notifications\Notifiable;بعد ما نیاز داریم که روتی برای نماش فرم درخواست رمز عبور مطابق کد زیر تعریف کنیم:Route::get('/forgot-password', function () { return view('auth.forgot-password'); })->middleware('guest')->name('password.request');در کد بالا تنها یه ویو به کاربر نشون میدیم که داخلش باید ایمیل email کاربر رو دریافت کنیم و به روت بعدی پست کنیم. همچنین از میدلور guest استفاده شده تا کاربرانی که لاگین هستن دیگه نتونن این صفحه رو ببینند. اسم روت هم که طبق روال از پیش تعیین شده.use Illuminate\Http\Request; use Illuminate\Support\Facades\Password; Route::post('/forgot-password', function (Request $request) { $request->validate(['email' => 'required|email']); //اعتبار سنجی ایمیل $status = Password::sendResetLink( $request->only('email') ); //پیدا کردن کاربری با ایمیل وارد شده و ارسال ایمیل بازیابی رمز return $status === Password::RESET_LINK_SENT //تنظیم سشن برای نمایش نتیجه درخواست ? back()->with(['status' => __($status)]) : back()->withErrors(['email' => __($status)]); })->middleware('guest')->name('password.email');همانطور که تو کامنت های دستورات بالا مشخص کردم وضعیت ارسال ایمیل توی سشن status ریخته میشه که میتونیم توی صفحه درخواست ایمیل بازیابی اون رو به کاربر نشون بدیم اون هم مربوط به ویو میشه ولی به هر حال مطابق کد های زیر میشه این کار رو تو ویو کرد:@if (Session::has('status')) //اگر همچین سشنی ست شده بود <div class=&quotalert alert-success&quot role=&quotalert&quot> {{ Session::get('status') }} //پیغامشو نمایش بده </div> @endifحالا دیگه باید ایمیل حاوی لینک بازیابی رمز هم برای کاربر فرستاده شده باشه و در ویو هم پیغام ارسال موفقیت آمیز ایمیل رو ببینه. حالا باید بریم سراغ روتی که کاربر بعد از کلیک روی لینک ایمیل شده بهش، واردش میشه:Route::get('/reset-password/{token}', function ($token) { return view('auth.reset-password', ['token' => $token]); })->middleware('guest')->name('password.reset');همانطوری که در کدهای بالا میبینید روت ما توکن ارسال شده رو دریافت میکنه و داخل متغیر token میریزه بعد یه ویو به کاربر نشون میدیم که توکن دریافتی هم بهش ارسال میشه. توی این ویو ما یک فرمی خواهیم داشت با یک input مخفی که value اش میشه مقدار token و یک فیلد برای ایمیل کاربر "email" و فیلد های رمز عبور جدید "password" و تکرار رمز عبور جدید "password_confirmation" که این داده ها پست میشن به روت بعدی تا رمز عبور عوض بشه:use Illuminate\Auth\Events\PasswordReset; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Password; use Illuminate\Support\Str; Route::post('/reset-password', function (Request $request) { $request->validate([ //اهتبار سنجی داده ها 'token' => 'required', 'email' => 'required|email', 'password' => 'required|min:8|confirmed', ]); $status = Password::reset( //ساخت کوئری و واکشی کاربر مورد نظر $request->only('email', 'password', 'password_confirmation', 'token'), function ($user, $password) { $user->forceFill([ 'password' => Hash::make($password) //تغییر رمز عبور ])->setRememberToken(Str::random(60)); //تغییر توکن کاربر $user->save(); //ذخیره کاربر event(new PasswordReset($user)); } ); return $status === Password::PASSWORD_RESET //تنظیم سشن برای نمایش وضعیت درخواست ? redirect()->route('login')->with('status', __($status)) : back()->withErrors(['email' => [__($status)]]); })->middleware('guest')->name('password.update');خب دوستان اینم از بخش بازیابی رمز عبور که تا اینجا کامل امکانات مورد نیاز احراز هویت کاربران توی لاراول رو پیاده سازی کردیم :)فارسی سازی پیغام هاپیغام های اعتبار سنجی لاراول به صورت پیش فرض انگلیسی هستند، همچنین ایمیل تایید ای که ما در بالا برای کاربر فرستادیم هم به صورت انگلیسی ارسال میشه. اگر میخواید این پیغام ها فارسی بشن می تونید در صفحه گیت هاب من پکیجی که برای این کار آماده شده رو دانلود و پیغام های لاراول رو فارسی کنید. توضیحات پکیج هم همونجا داده شده.آدرس پروژه در گیت هاب: https://github.com/arashmehrani/laravel-persian-langخب دوستان، تونستیم بدون استفاده از پکیج های جانبی و به صورت دستی بخش های ثبت نام، ورود و خروج رو با استاندارد های خود هسته لاراول پیاده سازی کنیم. امیدوارم از این مقاله استفاده لازم رو برده باشید.