در بسیاری از اپلیکیشنهای لاراولی، نیاز است تا احراز هویت کاربران را با استفاده از تلفن همراه و ارسال اس ام اس در لاراول انجام دهیم. در بسیاری از اپلیکیشنهای موجود، برای ورود کاربر، علاوه بر گزینهی ورود با ایمیل و رمز عبور، گزینهی ورود به وسیلهی ارسال کد تایید تلفن همراه نیز وجود دارد. در این مقاله، قصد داریم نحوهی ایجاد این ویژگی را در قالب یک مثال عملی و به صورت کاربردی برای شما تشریح کنیم. پس تا انتهای مقاله با ما همراه باشید تا با نحوهی احراز هویت با موبایل در لاراول آشنا شوید.
اگر تو هم به فریم ورک لاراول علاقهمندی و دوست داری در این زمینه حرفه ای بشی و کسب درآمد کنی پیشنهاد میکنیم در دوره آموزش لاراول سون لرن شرکت کنی تا از مزایا یکسال پشتیبانی دوره بهرهمند بشی.
نیازمندیهای اولیه
برای شروع آموزش احراز هویت پیامکی با موبایل در لاراول، به دانش کافی در زمینهی لاراول نیاز دارید.
نصب لاراول
به پوشهی دلخواه خود بروید و دستور زیر را برای نصب لاراول اجرا کنید:
composer create-project --prefer-dist laravel/laravel blog
با دستور زیر میتوانید پروژه را اجرا کنید:
php artisan serve
پس از اجرای این دستور، پروژه بر روی پورت 8000 لوکال هاست در دسترس است. با وارد کردن آدرس http://localhost:8000 در نوار آدرس مرورگر، با این صفحه مواجه میشوید:
راهاندازی دیتابیس
قدم بعدی، برقراری ارتباط با دیتابیس است. ابتدا یک دیتابیس دلخواه را ایجاد کنید و سپس مقادیر متغیرهای زیر را در فایل env. پروژه بهروز کنید:
در اینجا میخواهیم مدلها را بهروزرسانی و متدهایی را به آنها اضافه کنیم.
مدل کاربران
مدل User را به شکل زیر بهروز کنید:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'password',
'phone'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* User tokens relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function tokens()
{
return $this->hasMany(Token::class);
}
}
در کد بالا مشاهده میکنید که رابطهی hasMany را بین جدول کاربران و جدول توکنها تعریف کردهایم.
مدل توکن
برای مدل توکن، متدهای مختلفی را تعریف میکنیم:
<?php
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Token extends Model
{
use HasFactory;
const EXPIRATION_TIME = 15; // minutes
protected $fillable = [
'code',
'user_id',
'used'
];
public function __construct(array $attributes = [])
{
if (! isset($attributes['code'])) {
$attributes['code'] = $this->generateCode();
}
parent::__construct($attributes);
}
/**
* Generate a six digits code
*
* @param int $codeLength
* @return string
*/
public function generateCode($codeLength = 4)
{
$max = pow(10, $codeLength);
$min = $max / 10 - 1;
$code = mt_rand($min, $max);
return $code;
}
/**
* User tokens relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
/**
* True if the token is not used nor expired
*
* @return bool
*/
public function isValid()
{
return ! $this->isUsed() && ! $this->isExpired();
}
/**
* Is the current token used
*
* @return bool
*/
public function isUsed()
{
return $this->used;
}
/**
* Is the current token expired
*
* @return bool
*/
public function isExpired()
{
return $this->created_at->diffInMinutes(Carbon::now()) > static::EXPIRATION_TIME;
}
public function sendCode()
{
if (! $this->user) {
throw new \Exception("No user attached to this token.");
}
if (! $this->code) {
$this->code = $this->generateCode();
}
try {
// send code via SMS
} catch (\Exception $ex) {
return false; //enable to send SMS
}
return true;
}
}
در کد بالا مشاهده میکنید که متد ()generateCode را برای ایجاد اعداد تصادفی، متد ()isValid را برای بررسی اعتبار کد، متد ()isUsed را برای بررسی کد استفاده شده و متد ()isExpired را برای بررسی انقضای کد تعریف کردهایم. همچنین ثابت EXPIRATION_TIME را به عنوان مدت انقضای کد در واحد دقیقه تعریف نمودهایم.
متد ()sendCode را برای ارسال کد تایید برای کاربر تعریف کردهایم. در این متد، ابتدا در صورت عدم وجود رابطهی ()user، یک Exception را Throw کردهایم. سپس، در صورت عدم ایجاد کد که در متد ()construct__ تعریف کردهایم، یک کد جدید را ایجاد میکنیم. درون بلاک try، بسته به سرویس پیامکی دلخواهی که استفاده میکنید، کد ارسال پیامک سرویس موردنظر را وارد کنید. در صورت بروز هرگونه مشکل نیز، اخطار به وجود آمده را در بلاک ()catch مدیریت کنید.
ایجاد Viewها
اکنون نیاز داریم قالب Blade صفحات موردنیازمان را ایجاد کنیم.
با استفاده از دستور زیر کنترلر AuthController را ایجاد میکنیم:
php artisan make:controller AuthController
متدهای ثبت نام
برای ثبت نام از متدهای register و doRegister استفاده میکنیم. همانطور که میبینید در اعتبارسنجی دادههای ارسالی، ورود شمارهی موبایل را اختیاری قرار دادهایم:
public function register()
{
return view('auth.register');
}
public function doRegister(Request $request)
{
$data = $request->all();
$this->validate($request, [
'name' => 'required',
'email' => 'required|email|unique:users',
'password' => 'required|confirmed',
'phone' => 'nullable|numeric',
]);
$data['password'] = bcrypt($request->password);
$user = User::create($data);
auth()->login($user);
return redirect()->route('index');
}
public function loginPhone()
{
return view('auth.login-phone');
}
متدهای ورود با ایمیل
برای ورود با ایمیل از دو متد loginEmail و doLoginEmail استفاده میکنیم:
public function loginEmail()
{
return view('auth.login-email');
}
public function doLoginEmail(Request $request)
{
$this->validate($request, [
'email' => 'required',
'password' => 'required'
]);
$data = $request->only('email', 'password');
$rememberMe = $request->input('remember_me');
if (auth()->attempt($data, $rememberMe))
return redirect()->route('index');
else
return redirect()->back()->withErrors('Either email or password is wrong.');
}
متدهای ورود با موبایل
برای ورود با موبایل از دو متد loginPhone و doLoginPhone استفاده میکنیم:
همانطور که میبینید، برای ارسال کد از متد ()sendCode موجود در مدل Token استفاده کردهایم. در صورت موفقیتآمیز بودن ارسال کد، سه مقدار شناسهی توکن ارسالی، شناسهی کاربر و مقدار فیلد Remember Me یا مرا به خاطر بسپار را در سشن ذخیره کردهایم. از این مقادیر در متد مربوط به تایید کد استفاده خواهیم کرد.
متدهای تایید کد
برای تایید کد ارسالی دو متد verify و doVerify را تعریف میکنیم. در اینجا، اعتبارسنجی شماره موبایل در لاراول را انجام میدهیم:
public function verify() {
return view('auth.verify');
}
public function doVerify(Request $request) {
$this->validate($request, [
'code' => 'required|numeric'
]);
if (!session()->has('code_id') || !session()->has('user_id'))
redirect()->route('loginPhone');
$token = Token::where('user_id', session()->get('user_id'))->find(session()- >get('code_id'));
if (!$token || empty($token->id))
redirect()->route('loginPhone');
if (!$token->isValid())
redirect()->back()->withErrors('The code is either expired or used.');
if ($token->code !== $request->input('code'))
redirect()->back()->withErrors('The code is wrong.');
$token->update([
'used' => true
]);
$user = User::find(session()->get('user_id'));
$rememberMe = session()->get('remember');
auth()->login($user, $rememberMe);
return redirect()->route('index');
}
همانطور که میبینید، پس از اعتبارسنجی، وجود مقادیر سشنها را بررسی کردهایم تا از ارسال درخواستهای متفرقه جلوگیری شود. در ادامه، با استفاده از مقادیر موجود در سشن، رکورد مربوط به کد را به دست میآوریم و سپس با استفاده از متد ()isValid موجود در مدل Token، آن را اعتبارسنجی میکنیم. سپس کد ارسال شده از سمت کاربر را با کد موجود در رکورد، مقایسه میکنیم و اعتبارسنجی شماره موبایل در لاراول را انجام میدهیم. در انتها نیز با استفاده از مقدار Remember Me موجود در سشن در متد ()login، کاربر را لاگین میکنیم. به این صورت میتوانیم لاگین با شماره موبایل در لاراول را عملی کنیم.
متد خروج
برای خروج هم از متد logout، به صورت زیر استفاده میکنیم:
public function logout()
{
auth()->logout();
return redirect()->back();
}
اکنون پروژهی لاگین با شماره تلفن در لاراول آماده است و به عنوان مثال، با مراجعه به آدرس http://localhost:8000/register، با صفحهی زیر مواجه میشوید:
جمعبندی
در این مقاله از سری مقالات آموزش لاراول، با نحوهی احراز هویت با موبایل در لاراول آشنا شدیم و توانسیتم علاوه بر احراز هویت به وسیلهی ایمیل و رمز عبور، روش احراز هویت پیامکی در لاراول را نیز با مثال عملی بیاموزیم و نحوهی تایید شماره موبایل در لاراول را فرابگیریم. از الگوی معرفی شده در این مقاله، میتوانید به هر صورتی که نیاز داشتید استفاده کنید. میتوانید فقط از روش احراز هویت با SMS در لاراول استفاده کنید و از ایمیل و رمز عبور صرفنظر کنید. در این صورت، ستون Phone در جدول Users اجباری میشود و پس از ثبت نام نیز باید شمارهی همراه وارد شده توسط کاربر را با ارسال کد تایید پیامکی، اعتبارسنجی کنید.
امیدوار هستیم که این مقاله برای شما مفید بوده باشد. خوشحال میشویم نظرات، تجربیات و سوالات خود را با ما و سایر کاربران سون لرن به اشتراک بگذارید.
۲۵ دیدگاه
۱۲ مرداد ۱۴۰۲، ۲۰:۴۷
متد doVerify مشکل داره . اون جاهایی ک چک میکنی otp فرستاده شده برابر ورودی کاربر باشه باید برای ریدایرکت return کنی ک نکردی و همین کاری میکنه که کاربر بتونه با هر کدی ورود کنه ! و otp در واقع چک نمیشه !
return redirect()-&gt;back()-&gt;withErrors(&#39;The code is either expired or used.&#39;);
این شکلی درست میشه .
نازنین کریمی مقدم۱۵ مرداد ۱۴۰۲، ۱۰:۱۵
درود بر شما
ممنون که به دوستان سون لرنی کمک میکنید :)
۱۴ شهریور ۱۴۰۱، ۱۲:۱۴
اساتید محترم یه تیکه کد کم داشتم خلاصه نزدیک 60ساعت نخوابیده بودم تا اینکه این کد شما رو دیدم
هرکس این آموزش رو گذاشته خدا امواتش رو بیامرزه
واقعا آفرین و دستتون درد نکنه
Big LIKE 10^
۰۷ شهریور ۱۴۰۱، ۱۸:۱۸
سلام این همه زحمت کشیدید عنوان آموزش هست تایید با موبایل همه چی هست اما موبایل نیست کدوم سرویس مخابراتی استفاده کردید؟ اصلا سرویس ارسال و دریافت پیامک کجاست؟
نازنین کریمی مقدم۰۸ شهریور ۱۴۰۱، ۰۴:۲۶
درود
اگر با دقت کدها رو بخونید متوجه میشید که خود برنامه برای تست کد رو جنریت میکنه. اگر میخواید از سامانههای ملی پیامک و امثالهم استفاده کنید باید داکیومنت استفاده رو از سایت خودشون بردارید و مطالعه فرمایید.
۲۴ مرداد ۱۴۰۱، ۱۷:۰۴
با سلام
ممنون از آموزش شما
میشه سورس پروژه را هم در سایت قرار دهید؟
باتشکر
akarimiii۰۴ خرداد ۱۴۰۱، ۱۱:۱۴
برای اینکه از ساخته شدن احتمالی کد تکراری جلوگیری بعمل بیارید بهتره در migration خودتون row مربوط به code رو به این شکل عوض کنید.
$table->string('code', 4)->unique();
۲۵ بهمن ۱۴۰۰، ۱۱:۲۸
سلام وقت بخیر امکانش هست همین آموزش به اضافه صف بندی رو هم بگین؟
صادق موسی زاده۰۱ مهر ۱۴۰۰، ۱۵:۲۳
سلام وقت بخیر
متد login() داخل کدتون نیست.
عماد نعیمیفر۰۵ دی ۱۴۰۰، ۲۱:۴۱
سلام. نه نیست. اگه یه بار دیگه مقاله رو مطالعه بفرمایید میبینید که از متدهای loginPhone و loginEmail استفاده شده و خبری از متد login نیست.
امید۰۷ شهریور ۱۴۰۰، ۰۶:۲۱
درود.
Call to undefined method App\Http\Controllers\Token::create()
شما توی فایل AuthController متد create برای ساخت تاکن رو صدا زدید اما همچین چیزی وجود نداره.!! چرا؟
عماد نعیمیفر۰۵ دی ۱۴۰۰، ۲۱:۳۹
سلام. دو نکته. اول اینکه اصلا کلاس Token رو اشتباهی use کردید. کلاس Token کلاس مدل هست و نه کلاس کنترلر. توی مقاله هم حرفی از کلاس کنترلر Token زده نشده و فقط کلاس مدل Token وجود داره. یعنی یه چیزی شبیه به
use App\Token
( یا البته کمی هم احتمال داره use App\Models\Token)
و نکته دوم اینکه اون متد create یک متد الکوئنت هست و جزو متدهای از پیش تعریف شده پکیچ ایلومینیت لاراول هست. شما اگه کلاس Token درست رو use کنید دیگه نیاز نیست نگران متد create باشد و فکر کنم این خطاتون برطرف بشه.
مرتضی۰۲ خرداد ۱۴۰۰، ۱۲:۱۵
خیلی متشکرم بابت این مقاله کاربردی ?
abbgol۲۳ فروردین ۱۴۰۰، ۱۹:۰۳
کار بسیار جالبیه فقط مسئله middleware رو باید چکار کرد . راستش من تو لاراول خیلی مبتدی هستم
نازنین کریمی مقدم۲۷ فروردین ۱۴۰۰، ۱۵:۱۲
بنظرم تا حد امکان فعلا سراغ middleware نرید و جواب تیک خورده رو امتحان کنید.
اگر نشد و نیاز به middleware بود، باید از طریق دورهها یادش بگیرید چون در قالب کامنت و مقاله نمیگنجه و باید به صورت عملی تست کنید.
abbgol۲۱ فروردین ۱۴۰۰، ۱۳:۱۲
سلام بسیار عالی است من همه مراحل رو رفتم ولی هنگام ارسال شماره موبایل با خطای
Route [login] not defined.
D:\wamp64\www\mobileAuth\vendor\laravel\framework\src\Illuminate\Routing\UrlGenerator.php:429
روبرو میشم
ممنون میشم راهنمایی بفرمائید
نازنین کریمی مقدم۲۱ فروردین ۱۴۰۰، ۱۴:۲۸
سلام.
خطا برای این هست که شما میخواید به login روت کنید اما مسیری با این نام وجود نداره و تو بخش روتر تعریف نشده. برای اطلاعات بیشتر میتونید راه حلهای مشکل رو در<a href="https://stackoverflow.com/questions/29303783/route-login-not-defined" target="_blank" rel="noopener nofollow ugc"> این پست استک </a>ببینید.
محمد۱۶ فروردین ۱۴۰۰، ۱۳:۲۵
باسلام این مشکل داره ؟ موقعی که کدتایید میزنی هر کدی بزنی وارد میشه این نباید باشه؟؟
نازنین کریمی مقدم۱۷ فروردین ۱۴۰۰، ۰۹:۴۲
درود.
احتمالا مشکل از بخش اعتبارسنجی باشه.
عماد نعیمیفر۰۶ دی ۱۴۰۰، ۲۰:۰۵
سلام. دلیلش اینه که توی متد doVerify اشتباها قبل از بعضی از redirectها وآزه return قرار نگرفته. اونو بذارید درست میشه.
akarimiii۰۴ خرداد ۱۴۰۱، ۱۱:۱۱
برای اعتبار سنجی درست در کنترلر خودتون و تابع doVerify از Rule برابر با exists باید استفاده کنید. این رول اجازه میده بررسی کنید که آیا این کد داخل دیتابیس وجود داره یا نه.قسمت اعتبار سنجی به این شکل تغییر میکنه
'code' => 'required|numeric|exists:tokens'
وحید گروسی۱۲ آذر ۱۳۹۹، ۰۷:۱۲
این لینکی که ارسال کردید احراز هویت با استفاده از ایمیل است نه موبایل
نازنین کریمی مقدم۱۲ آذر ۱۳۹۹، ۱۰:۰۵
درود.
اوکیه ما یه مقاله رو در آینده به این موضوع اختصاص میدیم. ممنون که با ما همراه هستید.
وحید گروسی۱۱ آذر ۱۳۹۹، ۱۱:۳۶
سلام وقتتون بخیر بسیار عالی لطفاً از طریق API هم آموزش بسازید
نازنین کریمی مقدم۱۱ آذر ۱۳۹۹، ۱۷:۰۳
درود.
قبلا پوشش دادیم. میتونید مقاله<a href="https://7learn.com/blog/laravel-authentication-with-api" rel="noopener noreferrer" target="_blank"> احراز هویت با API در لاراول </a>رو مطالعه کنید.