بهینهسازی تجربه کاربری در احراز هویت چندعاملی: نقش صفت معنایی autocomplete=one-time-code
نویسنده: وحید نصیری
تاریخ: ۱۴۰۵/۰۶/۱۱ ۱۰:۲۵
آدرس: www.dntips.ir
چکیده: احراز هویت چندعاملی (MFA) و کدهای یکبارمصرف (OTP) به استانداردی فراگیر در امنیت سامانههای تحت وب تبدیل شدهاند. با این حال، افزایش لایههای امنیتی غالباً با کاهش سهولت کاربری (UX) و اصطکاک تعاملی -بهویژه در دستگاههای همراه- همراه است. در معماریهای مبتنی بر مایکروسافت داتنت (ASP.NET Core،BlazorوWeb Forms)، توسعهدهندگان معمولاً برای رفع این چالش به سراغ کتابخانههای جاوا اسکریپت یا پکیجهای ثالث میروند. این مقاله به بررسی و تحلیل یک راهکار بومی، استاندارد و متکی بر وب معنایی (Semantic HTML) یعنی استفاده از صفتautocomplete="one-time-code"به همراهinputmode="numeric"میپردازد. این ویژگی با بهرهگیری از توانایی مرورگرها و سیستمهای عامل در استخراج خودکار رمزهای یکبارمصرف (SMS/Email)، بدون تحمیل سربار پردازشی یا افزودن وابستگیهای خارجی، نرخ موفقیت لاگین را بهبود میبخشد. همچنین در این نوشتار، چالش رابطهای کاربری چندورودی (Split-box Inputs)، تمایز این رویکرد با استاندارد WebOTP API و ملاحظات امنیت SMS مبتنی بر دامنه (Domain-bound SMS) تبیین شده است.
autocomplete="one-time-code"و تقابل آن باinputmodeautocomplete برای عناصر ورودی فرم تعریف کرده است. مقدار اختصاصی one-time-code صراحتاً به مرورگر و عامل کاربر (User Agent) اعلام میکند که این فیلد در انتظار یک رمز یکبارمصرف جهت تأیید هویت است.autocomplete و inputmode را با یکدیگر اشتباه میگیرند یا یکی را جایگزین دیگری فرض میکنند:autocomplete="one-time-code" (معنا و رفتار): نشاندهنده ماهیت داده است. این صفت به مرورگر، سیستمعامل (iOS، اندروید) و ابزارهای مدیریت گذرواژه (مانند Bitwarden یا 1Password) میگوید که مقادیر دریافتی در کلیپبورد یا پیامکهای اخیر را بررسی و پیشنهاد تکمیل خودکار (Autofill Suggestion) را فعال کنند.inputmode="numeric" (رابط کاربری ورود داده): صرفاً ظاهر صفحهکلید مجازی در دستگاههای لمسی را تنظیم میکند تا مستقیماً پد عددی (Numpad) به جای کیبورد کامل حروفی نمایش داده شود.<input type="text"
autocomplete="one-time-code"
inputmode="numeric"
maxlength="6" />@model MfaVerificationViewModel
<form asp-action="VerifyMfa" method="post">
<label asp-for="Code">کد تأیید ارسالشده را وارد کنید:</label>
<input asp-for="Code"
class="form-control text-center"
autocomplete="one-time-code"
inputmode="numeric"
maxlength="6"
placeholder="------" />
<span asp-validation-for="Code" class="text-danger"></span>
<button type="submit" class="btn btn-primary mt-3">تأیید و ورود</button>
</form>InputText با پشتیبانی کامل از صفتهای تکمیلی انجام میپذیرد:@using System.ComponentModel.DataAnnotations
<EditForm Model="@authModel" OnValidSubmit="HandleVerification">
<DataAnnotationsValidator />
<InputText @bind-Value="authModel.OtpCode"
class="form-control"
autocomplete="one-time-code"
inputmode="numeric"
maxlength="6" />
<button type="submit" class="btn btn-success mt-2">بررسی کد</button>
</EditForm>
@code {
private AuthModel authModel = new();
public class AuthModel
{
[Required(ErrorMessage = "کد تأیید الزامی است.")]
[StringLength(6, MinimumLength = 6, ErrorMessage = "کد باید ۶ رقم باشد.")]
public string OtpCode { get; set; } = string.Empty;
}
private void HandleVerification()
{
// فراخوانی منطق احراز هویت
}
}TextBox خصوصیتی موسوم به AutoCompleteType دارد. این خصوصیت متعلق به معماری قدیمی داتنت است و از مقادیر مشخص HTML5 پشتیبانی نمیکند؛ بنابراین نباید از AutoCompleteType برای OTP استفاده کرد. راهحل صحیح، افزودن مستقیم صفت در نشانهگذاری یا از طریق کد سمت سرور است:<asp:TextBox ID="txtOtp"
runat="server"
MaxLength="6"
autocomplete="one-time-code"
inputmode="numeric" />protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
txtOtp.Attributes.Add("autocomplete", "one-time-code");
txtOtp.Attributes.Add("inputmode", "numeric");
txtOtp.Attributes.Add("maxlength", "6");
}
}┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │ 4 │ │ 8 │ │ 2 │ │ 9 │ │ 1 │ │ 3 │ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘
autocomplete="one-time-code" روی هر ۶ تگ ورودی، رفتار موتور Autofill مرورگر را مختل میکند؛ زیرا مرورگر رمز را یک موجودیت واحد (یک توکن ۶ رقمی) درک میکند و با این کار، کل کد ۶ رقمی را داخل اولین جعبه تککاراکتری تزریق مینماید یا رفتار آن با شکست مواجه میشود.<div class="otp-wrapper">
<!-- ورودی اصلی که داده را دریافت و ارسال میکند -->
<input type="text"
id="mainOtpInput"
class="sr-only-input"
autocomplete="one-time-code"
inputmode="numeric"
maxlength="6" />
<!-- خانههای نمایشی برای تجربه بصری کاربر -->
<div class="visual-boxes" aria-hidden="true">
<span class="box"></span>
<span class="box"></span>
<span class="box"></span>
<span class="box"></span>
<span class="box"></span>
<span class="box"></span>
</div>
</div>// دریافت برنامهریزیشده کد از طریق جاوا اسکریپت
if ('OTPCredential' in window) {
navigator.credentials.get({
otp: { transport: ['sms'] }
}).then(otp => {
document.getElementById('mainOtpInput').value = otp.code;
document.forms[0].submit(); // ارسال خودکار فرم
});
}| مشخصه | صفت autocomplete="one-time-code" | مکانیزم WebOTP API |
| نوع رویکرد | اعلانی (Declarative) با HTML | برنامهنویسیشده (Imperative) با JS |
| میزان پشتیبانی مرورگرها | بسیار وسیع (تمامی نسخههای مدرن Safari, Chrome, Edge) | محدودتر (بیشتر در کروم و اندروید) |
| امکان ثبت خودکار فرم | نیاز به اسکریپت واسط برای رویداد Change | قابلیت ثبت کامل و بدون دخالت مستقیم کاربر |
| سربار توسعه | حداقل (یک صفت بدون وابستگی) | نیاز به مدیریت خطا و Feature Detection |
autocomplete="one-time-code" را به عنوان پایه اصلی معماری خود مستقر کنید که روی تمامی بسترهای دسکتاپ و موبایل پاسخگوست؛ سپس در صورت نیاز به ارسال آنی و خودکار فرم (Auto-submit)، از WebOTP API به عنوان یک لایه بهبود تدریجی (Progressive Enhancement) بهره بگیرید.autocomplete="one-time-code" بهطور مخفیانه به پیامکهای شخصی کاربر دسترسی پیدا نمیکند؛ بلکه این سیستمعامل و مرورگر هستند که پیام را ارزیابی میکنند. برای تضمین امنیت و جلوگیری از حملات فیشینگ معکوس، کنسرسیوم W3C فرمت پیامکهای مقید به مبدأ (Origin-Bound One-Time Codes) را تعریف کرده است.کد ورود شما به سامانه: 482913. @yourdomain.com #482913
@: مشخصکننده دامنه وبسایت است.#: نشاندهنده کد تأیید است.autocomplete="one-time-code" همراه با inputmode="numeric" نمونهای بارز از قدرت وب معنایی و مهندسی استاندارد است.