چگونه در ۵ دقیقه احراز هویت دو مرحلهای (OTP) را به Laravel اضافه کنیم؟
چرا OTP دیگه یک انتخاب نیست، یک ضرورته؟ 🔐چرا OTP دیگه یک انتخاب نیست، یک ضرورته؟ 🔐اگر شما هم یک سایت فروشگاهی، سرویس آنلاین یا اپلیکیشن دارید، حتماً با این چالش روبرو شدید:چطور مطمئن بشم شماره موبایل کاربر واقعاً متعلق به خودشه؟چطور بدون پیچیدگی زیاد، امنیت ثبتنام رو بالا ببرم؟در سال ۱۴۰۴، احراز هویت دو مرحلهای (OTP) دیگه یک آپشن لوکس نیست. کاربران ایرانی بهشدت نسبت به امنیت حساس شدن و اگر سایت شما نتونه کد تایید بفرسته، احتمالاً رقیبتون رو انتخاب میکنن.اما مشکل اینجاست: خیلی از پنلهای پیامک یا مستندات ضعیفی دارن، یا پیادهسازیشون زمانبره، یا هزینههای پنهان دارن.در این مقاله، قراره در کمتر از ۵ دقیقه و با حدود ۳۰ خط کد، یک سیستم OTP کامل و امن به پروژه Laravel شما اضافه کنیم. بدون نیاز به پکیج اضافی، بدون پیچیدگی.چیزی که در پایان این مقاله دارید:✅ یک کنترلر کامل برای ارسال و بررسی کد تایید✅ کد آماده برای کپیپیست در پروژه✅ لینک دانلود پروژه کامل از گیتهاب✅ پیامک رایگان برای تستبریم شروع کنیم! 👇چه چیزهایی نیاز داریم؟ 📋قبل از شروع، مطمئن شو این موارد رو داری:Laravel 8 یا بالاتراکانت PromoSMSAPI Token - از پنل کاربری قابل دریافته (رایگان)آشنایی مقدماتی با لاراول💡 نکته: اگر هنوز اکانت نداری، همین الان ثبتنام کن. پیامک رایگان برای تست بهت هدیه میدیم.ساخت کنترلر OTP 🎮اولین قدم، ساخت یک کنترلر برای مدیریت ارسال و بررسی کد تاییده.در ترمینال پروژهت این دستور رو اجرا کن:php artisan make:controller OtpControllerحالا فایل app/Http/Controllers/OtpController.php رو باز کن و این کدها رو اضافه کن:<?php namespace App\Http\Controllers; use Illuminate\Http\Client\ConnectionException; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; class OtpController extends Controller { /** * ارسال کد تایید به شماره موبایل * @throws ConnectionException */ public function send(Request $request) { // اعتبارسنجی شماره موبایل $request->validate([ 'phone' => ['required', 'size:11', 'regex:/^09[0-9]{9}$/'] ]); $phone = $request->phone; // تولید کد ۵ رقمی تصادفی $code = str_pad(rand(1, 99999), 5, 0, STR_PAD_LEFT); // ذخیره کد در کش به مدت ۲ دقیقه Cache::put('otp_' . $phone, $code, 120); // ارسال پیامک با PromoSMS $response = Http::withToken(config('services.promosms.token')) ->withHeaders([ 'Accept' => 'application/json', ]) ->post('https://promosms.ir/api/send/pattern', [ 'number' => $phone, 'data' => [ 'data1' => $code, ], 'pattern_code' => config('services.promosms.patterns.login') ]); // لاگگیری برای دیباگ Log::info("OTP sent to {$phone}", [ 'status' => $response->successful(), 'code' => $response->status(), 'report_id' => $response->json()['info']['report_id'], ]); return response()->json([ 'success' => $response->successful(), 'message' => $response->successful() ? 'کد تایید ارسال شد' : 'خطا در ارسال پیامک' ]); } /** * بررسی کد تایید واردشده توسط کاربر */ public function verify(Request $request) { $request->validate([ 'phone' => 'required|size:11', 'code' => 'required|size:5' ]); $phone = $request->phone; $code = $request->code; // دریافت کد ذخیرهشده از کش $storedCode = Cache::get('otp_' . $phone); if (!$storedCode) { return response()->json([ 'success' => false, 'message' => 'کد تایید منقضی شده یا وجود ندارد' ], 400); } // بررسی صحت کد if ($storedCode != $code) { return response()->json([ 'success' => false, 'message' => 'کد تایید اشتباه است' ], 400); } // حذف کد از کش پس از موفقیت Cache::forget('otp_' . $phone); return response()->json([ 'success' => true, 'message' => 'تایید هویت با موفقیت انجام شد' ]); } }تعریف روتها 🛣️حالا باید روتهای API رو تعریف کنیم. فایل routes/api.php رو باز کن:// ارسال کد تایید (با محدودیت 1 درخواست در 2دقیقه) Route::post('/otp/send', [OtpController::class, 'send']) ->middleware('throttle:1,2'); // بررسی کد تایید Route::post('/otp/verify', [OtpController::class, 'verify']);⚠️ نکته امنیتی حیاتی:میدلور throttle:1,2 یعنی هر کاربر حداکثر میتونه ۱ درخواست در ۲دقیقه بفرسته. این برای جلوگیری از اسپم و سوءاستفاده ضروریه.تنظیمات API Key ⚙️برای اینکه کد کار کنه، باید API Token و Sender رو به پروژه اضافه کنی.فایل config/services.php رو باز کن و این بخش رو اضافه کن'promosms' => [ 'token' => env('PROMOSMS_API_TOKEN'), 'patterns' => [ 'login' => env('PROMOSMS_PATTERN_CODE_LOGIN') ], ],حالا در فایل .env این مقادیر رو اضافه کن:#-------Custom Env------ PROMOSMS_API_TOKEN=your_api_token_here PROMOSMS_PATTERN_CODE_LOGIN=your_pattern_codeتست با Postman 🧪حالا وقتشه که ببینیم کد واقعاً کار میکنه!درخواست ارسال OTP: (فقط کافیه کد زیر رو توی postman وارد کنید تا تنظیمات به صورت خودکار انجام بشه)curl --location 'http://127.0.0.1:8000/api/otp/send' \ --header 'Content-Type: application/json' \ --data '{ "phone": "09111111111" }'خروجی کد بالا باید بشه{ "success": true, "message": "کد تایید ارسال شد" }درخواست بررسی OTP:curl --location 'http://127.0.0.1:8000/api/otp/verify' \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --data '{ "phone":"09111111111", "code":"80910" }'خروجی کد بالا باید بشه{ "success": true, "message": "تایید هویت با موفقیت انجام شد" }⚠️ نکات امنیتی که باید رعایت کنیمحدودیت تعداد درخواست (Rate Limiting)همونطور که دیدید، از میدلور throttle استفاده کردیم. این جلوگیری میکنه از:اسپم شدن شماره کاربرانهزینه اضافی برای توحملات Brute Forceاعتبار زمانی کد (Expiration)کد ما فقط ۲ دقیقه اعتبار داره. بعد از این زمان، کش منقضی میشه و کاربر باید دوباره درخواست بده.عدم نمایش خطای دقیقدر پاسخ خطا، هیچوقت نگو «این شماره ثبتنام نشده» یا «کد اشتباهه، ۲ بار دیگه شانس داری». این اطلاعات به هکرها کمک میکنه.لاگگیری تلاشهای ناموفقبرای تشخیص حملات، حتماً تلاشهای ناموفق رو لاگ کنif ($storedCode != $code) { Log::warning("Failed OTP attempt for {$phone}"); // ... }🎁 هدیه ویژه: پروژه آماده گیتهابمیدونم که بعضی وقتها کپیپیست کردن کد از روی مقاله سخته. برای همین، کل این پروژه رو بهصورت آماده در گیتهاب گذاشتم.# 1. کلون کردن پروژه git clone https://github.com/PromoSmsIR/promosms-laravel-otp-example.git # 2. نصب وابستگیها cd promosms-laravel-otp-example composer install # 3. کپی فایل محیطی cp .env.example .env php artisan key:generate # 4. تنظیم API Key در فایل .env #-------Custom Env------ PROMOSMS_API_TOKEN=your_api_token_here PROMOSMS_PATTERN_CODE_LOGIN=your_pattern_code # 5. اجرای سرور php artisan serveدر این ریپو پیدا میکنی:✅ کد کامل کنترلر و روتها✅ فایل .env.example آماده✅ کلکشن Postman برای تست سریع✅ راهنمای فارسی در README🎯 حالا با این چیکار میتونم بکنم؟ثبتنام کاربران (تایید شماره موبایل هنگام ثبتنام)ورود دو مرحلهای (افزایش امنیت حسابهای کاربری)تایید تراکنش (ارسال کد برای پرداختهای حساس)بازیابی رمز (ارسال کد برای ریست پسورد)❓ سوالی داری؟اگر در حین پیادهسازی به مشکلی خوردی، یا ایدهای برای بهبود کد داری، حتماً در کامنتها بنویس. شخصاً جواب میدم و اگر باگی پیدا کردی، خوشحال میشم گزارش بدی تا ریپو رو آپدیت کنم.اگر این مقاله برات مفید بود:👍 بوکمارک کن که گمش نکنی🔄 برای همتیمیهات بفرست💬 تجربهت رو درباره OTP در کامنتها بنویسموفق باشید! 💙لینک های مفیدثبتنام و تست رایگانآدرس مخزن گیتهابچگونه یک سرویس پیامک انبوه را با Laravel ساختیم؟ (از ایده تا اجرا)#لاراول #OTP #احراز_هویت #برنامه_نویسی #PromoSMS #امنیت_وب #استارتاپ #پیامک