پاسخ کوتاه: OTP (One-Time Password) یک کد کوتاه و یکبارمصرف است که سایت یا اپلیکیشن به شمارهی موبایل کاربر پیامک میکند تا ثابت شود آن شماره واقعاً دست اوست. کاربر کد را وارد میکند و اگر درست و تاریخنگذشته باشد، وارد حساب میشود یا کارش (مثل ثبت سفارش) تأیید میشود. بدون رمز عبور، و برای همین هم سادهتر است و هم اگر درست پیاده شود، امنتر از رمزهای تکراری کاربران.
ما ورود به حساب کاربری سایت وستا را هم با همین روش ساختهایم؛ نکتههای این مقاله از همان تجربه آمده است.
ورود با پیامک OTP دقیقاً چطور کار میکند؟
- کاربر شمارهی موبایلش را وارد میکند.
- سرور یک کد تصادفی (معمولاً ۴ تا ۶ رقمی) میسازد، نسخهی هششدهاش را با زمان انقضا ذخیره میکند و خود کد را با وبسرویس پیامک میفرستد.
- کاربر کد را وارد میکند.
- سرور کد واردشده را با هش ذخیرهشده مقایسه میکند، تاریخ انقضا و تعداد تلاشها را میسنجد و اگر همهچیز درست بود، کد را باطل و کاربر را وارد میکند.
همهی تصمیمها باید روی سرور گرفته شود. اگر کد یا درست بودنش در مرورگر بررسی شود، هر کسی با ابزار توسعهدهندهی مرورگر میتواند آن را دور بزند.
پنج اشتباه رایج در پیادهسازی OTP
- نبود محدودیت تعداد درخواست: بدون محدودیت برای هر شماره و هر IP، رباتها میتوانند با درخواست پشت سر هم، شارژ پنل پیامک شما را خالی کنند یا شمارهی دیگران را با پیامک بمباران کنند.
- نبود محدودیت تعداد تلاش: کد ۴ رقمی فقط ۱۰ هزار حالت دارد. اگر تعداد تلاش برای هر کد محدود نباشد (مثلاً ۵ بار)، حدس زدنش کار سختی نیست.
- کد با عمر طولانی: کد باید چند دقیقه بیشتر اعتبار نداشته باشد و بعد از یک بار استفاده باطل شود.
- ذخیرهی کد به شکل خام: اگر دیتابیس نشت کند، کدهای فعال هم لو میروند. کد را مثل رمز عبور هش کنید.
- ساخت کد با تابع تصادفی ضعیف: در PHP از
random_intاستفاده کنید، نهrandیاmt_rand.
نمونه کد ساده در PHP
این نمونه فقط منطق سمت سرور را نشان میدهد (ساخت، ذخیره و بررسی کد). ارسال پیامک را با کتابخانه یا مستندات API پنل خودتان جایگزین کنید.
<?php
// ساخت و ذخیرهی کد (مثلاً در جدول otp_codes)
$code = (string) random_int(100000, 999999); // ۶ رقمی، تصادفی امن
$hash = password_hash($code, PASSWORD_DEFAULT); // کد خام ذخیره نمیشود
$expires = time() + 120; // ۲ دقیقه اعتبار
save_otp($mobile, $hash, $expires, 0); // ۰ = تعداد تلاشها
send_sms_pattern($mobile, array('code' => $code)); // ارسال با پترن پنل پیامک
// بررسی کد واردشده
$row = load_otp($mobile);
if (!$row || $row['expires'] < time() || $row['tries'] >= 5) {
deny('کد منقضی شده است؛ دوباره درخواست کنید.');
} elseif (!password_verify($input_code, $row['hash'])) {
increment_tries($mobile);
deny('کد درست نیست.');
} else {
delete_otp($mobile); // یکبارمصرف
login_user_by_mobile($mobile);
}
پرکردن خودکار کد در موبایل
دو کار کوچک تجربهی کاربر را خیلی بهتر میکند:
- به فیلد کد، ویژگی
autocomplete="one-time-code"بدهید تا کیبورد گوشی کد پیامکشده را پیشنهاد کند. - برای مرورگرهایی که از Web OTP API پشتیبانی میکنند، خط آخر پیامک را به شکل
@example.com #123456(دامنهی سایت خودتان و همان کد) بنویسید تا کد با اجازهی کاربر خودکار وارد شود.
فیلد کد را عددی کنید (inputmode="numeric") و دکمهی «ارسال دوباره» را تا پایان شمارش معکوس غیرفعال نگه دارید.
پترن و خط خدماتی: چرا کد تایید دیر میرسد؟
در پنلهای پیامک ایران، پیامهای خدماتی مثل کد تایید معمولاً با «پترن» فرستاده میشوند: متنی از پیش تعریفشده که فقط جای خالیاش (مثلاً خود کد) عوض میشود. پترن یک بار تأیید میشود و ارسالهای بعدی سریعتر و قابلاعتمادتر از ارسال متن آزاد انجام میشوند. خط خدماتی فقط برای پیامهای خدماتی است؛ اگر از آن پیام تبلیغاتی بفرستید، ممکن است مسدود شود.
چکلیست انتخاب وبسرویس پیامک OTP
- پشتیبانی از پترن و خط خدماتی برای ارسال کد تایید.
- API مستند و پایدار (معمولاً REST) با نمونه کد و پیامهای خطای روشن.
- گزارش تحویل تا بدانید پیامک واقعاً به گوشی رسیده یا در کدام مرحله مانده است.
- هشدار کم شدن شارژ تا ورود کاربران سایت بهخاطر تمام شدن اعتبار قطع نشود.
- تعرفهی شفاف و روشن بودن شرایط برداشت یا بازگشت شارژ استفادهنشده.
- پشتیبانی در دسترس در ساعتهایی که فروش شما بیشتر است.
وستا پیامک
در پنل پیامک وستا ارسال پترن و وبسرویس REST برای کد تایید (OTP) در دسترس است و سفارش آنلاین ثبت میشود. شارژ استفادهنشدهی بالای ۱ میلیون تومان قابل برداشت است (شرایط کامل در صفحهی بازگشت وجه). اگر سایتتان را از پایه میسازید، ورود پیامکی را میتوانیم در همان طراحی سایت پیاده کنیم.
پرسشهای پرتکرار
کد OTP چند رقمی باشد؟
۵ یا ۶ رقم تعادل خوبی بین امنیت و راحتی است. مهمتر از طول کد، محدود کردن تعداد تلاش و عمر کوتاه کد است.
ورود با OTP جای رمز عبور را کاملاً میگیرد؟
برای بیشتر فروشگاهها و سایتهای خدماتی بله؛ کاربر رمزی برای فراموش کردن ندارد. برای حسابهای خیلی حساس (مثل پنل مدیریت)، OTP را در کنار رمز عبور بهعنوان تأیید دومرحلهای استفاده کنید.
اگر پیامک نرسید چه کنیم؟
اول گزارش تحویل را در پنل ببینید. اگر پیامک از سمت اپراتور تحویل نشده، معمولاً مشکل از مسدود بودن دریافت پیامک تبلیغاتی روی خط کاربر یا اختلال اپراتور است؛ ارسال کد با خط خدماتی و پترن احتمال این مشکل را کم میکند.