اعتبارسنجی فرم توسط Web API
اگر مهاجرت به Identity یا OWIN برای پروژه شما ممکن نیست، اعتبارسنجی فرم توسط Web API هنوز یک راهحل کاربردی است. این روش در پروژههای قدیمی ASP.NET دیده میشود. همچنین برای سیستمهایی مناسب است که باید ساختار فعلی خود را حفظ کنند. در این مقاله، نحوه پیادهسازی این مدل را بهصورت ساده و کاربردی بررسی میکنیم. 🚀
در گذشته، بسیاری از پروژهها با Forms Authentication ساخته شدند. با ورود ASP.NET Identity، روشهای قدیمی کمتر استفاده شدند. با این حال، هنوز هم در برخی نرمافزارهای سازمانی، مهاجرت کامل ممکن نیست. در چنین شرایطی، استفاده از Web API برای مدیریت ورود و خروج کاربر میتواند انتخابی منطقی باشد.
هدف این مقاله، توضیح ساختار درست، مزیتها، کاربردها و مراحل اجرای اعتبارسنجی فرم توسط Web API است. در کنار آن، نکات مهم امنیتی و ثبتنام سریع در سرویس نیز مرور میشود.
اعتبارسنجی فرم توسط Web API چیست؟
اعتبارسنجی فرم توسط Web API روشی است که در آن اطلاعات ورود کاربر از طریق درخواست HTTP ارسال میشود. سپس سرور، هویت کاربر را بررسی میکند. اگر اطلاعات معتبر باشد، کوکی احراز هویت ساخته میشود و کاربر به بخشهای مجاز دسترسی پیدا میکند.
در این مدل، معمولاً چند بخش اصلی وجود دارد:
- دریافت اطلاعات ورود از سمت کاربر
- اعتبارسنجی نام کاربری و رمز عبور
- ساخت کوکی احراز هویت
- اختصاص نقش کاربر
- محدود کردن دسترسی بر اساس Role
این روش برای پروژههایی مفید است که هنوز از معماری قدیمی استفاده میکنند، اما میخواهند API محورتر شوند. ✅
چرا هنوز از Forms Authentication استفاده میشود؟
با اینکه Identity امکانات بیشتری دارد، اما همیشه انتخاب اول نیست. برخی تیمها به دلایل فنی یا تجاری، به سراغ بازنویسی کامل سیستم نمیروند.
مزیتها
- 🔹 سازگاری با پروژههای قدیمی: بدون بازنویسی کامل، میتوان احراز هویت را حفظ کرد.
- 🔹 پیادهسازی سریعتر: برای سیستمهای ساده، راهاندازی آن آسانتر است.
- 🔹 کنترل بیشتر بر روند احراز هویت: توسعهدهنده منطق را دقیقتر مدیریت میکند.
- 🔹 مناسب برای مهاجرت مرحلهای: میتوان بخشهایی از سیستم را به مرور نوسازی کرد.
- 🔹 پشتیبانی از Role-Based Authorization: کنترل دسترسی کاربران سادهتر میشود.
کاربردهای اعتبارسنجی فرم توسط Web API
این روش در سناریوهای مشخصی بیشترین ارزش را دارد.
کاربردها
- 🧩 پروژههای ASP.NET قدیمی
- 🧩 سامانههای سازمانی با ساختار Role-Based
- 🧩 وباپلیکیشنهایی که هنوز به Identity مهاجرت نکردهاند
- 🧩 سیستمهایی که Login و Logout را از طریق API مدیریت میکنند
- 🧩 پروژههایی که نیاز به حفظ Session و Cookie دارند
اگر پروژه شما به پایداری بیشتر از نوسازی کامل نیاز دارد، این مدل میتواند هنوز قابل اتکا باشد.
ساختار پیادهسازی
برای اجرای درست این روش، باید درخواستها و پاسخها کنترل شوند. در اینجا DelegatingHandler نقش مهمی دارد. این Handler هدرهای احراز هویت را بررسی میکند. سپس کاربر معتبر را به شیء HttpContext متصل میکند.
نقش DelegatingHandler
در پیادهسازی قدیمی Web API، از DelegatingHandler برای رهگیری درخواست استفاده میشود. این بخش اطلاعات هویت را از هدر درخواست میخواند. سپس در صورت معتبر بودن، یک Principal ساخته میشود. در نهایت، این Principal به Thread.CurrentPrincipal و HttpContext.Current.User اختصاص پیدا میکند.
این کار باعث میشود سیستم بتواند نقش کاربر را در متدهای مختلف تشخیص دهد. در نتیجه، محدودسازی دسترسی بر اساس Role ممکن میشود.
نمونه کد Handler
public class BasicAuthMessageHandler : DelegatingHandler
{
private const string BasicAuthResponseHeader = "WWW-Authenticate";
private const string BasicAuthResponseHeaderValue = "Basic";
public adminPrincipalProvider PrincipalProvider = new adminPrincipalProvider();
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
AuthenticationHeaderValue authValue = request.Headers.Authorization;
if (authValue != null && authValue.Parameter != "undefined" &&
!String.IsNullOrWhiteSpace(authValue.Parameter))
{
string email = authValue.Parameter;
if (HttpContext.Current.Session == null ||
HttpContext.Current.Session["userToken"] == null ||
string.IsNullOrEmpty(HttpContext.Current.Session["userToken"].ToString()))
{
HttpContext.Current.Session["userToken"] = email;
}
else
{
email = HttpContext.Current.Session["userToken"].ToString();
}
if (!string.IsNullOrEmpty(email))
{
IPrincipal principalObj = PrincipalProvider.createPrincipal(email, "Admin");
Thread.CurrentPrincipal = principalObj;
HttpContext.Current.User = principalObj;
}
}
return base.SendAsync(request, cancellationToken)
.ContinueWith(task =>
{
var response = task.Result;
if (response.StatusCode == HttpStatusCode.Unauthorized
&& !response.Headers.Contains(BasicAuthResponseHeader))
{
response.Headers.Add(BasicAuthResponseHeader,
BasicAuthResponseHeaderValue);
}
return response;
});
}
}
Login و Logout در Web API
برای مدیریت ورود و خروج کاربر، معمولاً دو متد جداگانه تعریف میشود. متد Login اطلاعات کاربر را دریافت میکند. سپس اگر اعتبارسنجی موفق باشد، کوکی احراز هویت ایجاد میشود.
نمونه متد ورود و خروج
[HttpPost, AllowAnonymous, Route("login")]
public async Task<HttpResponseMessage> Login([FromBody]LoginRequest request)
{
var loginService = new LoginService();
LoginResponse response = await loginService.LoginAsync(request.username, request.password);
if (response.Success)
{
FormsAuthentication.SetAuthCookie(response.Token, false);
}
return Request.CreateResponse(HttpStatusCode.OK, response);
}
[HttpPost, AllowAnonymous, Route("logout")]
public void Signout()
{
FormsAuthentication.SignOut();
if (HttpContext.Current.Session != null)
HttpContext.Current.Session.Abandon();
}
این پیادهسازی ساده است. با این حال، بهتر است در نسخه نهایی، کنترل خطا و لاگگیری هم اضافه شود. همچنین باید از نگهداری امن توکن و دادههای Session مطمئن شوید. 🔐
اعمال Role-Based Authorization
بعد از احراز هویت، نوبت کنترل دسترسی است. در این بخش، میتوانید تعیین کنید که چه کاربری به کدام Web Method دسترسی داشته باشد.
نمونه محدودسازی دسترسی
[HttpGet, Authorize(Roles = "admin"), Route("name")]
با این ویژگی، فقط کاربران دارای نقش admin به متد دسترسی دارند. این مدل برای پنل مدیریت و بخشهای حساس بسیار مفید است.
فراخوانی از سمت کلاینت
در سمت کاربر، میتوان با jQuery یا هر کتابخانه دیگر درخواست Login را ارسال کرد. نمونه زیر، یک روش ساده برای ارسال اطلاعات ورود را نشان میدهد.
$(document).ready(
function () {
$("#btnSubmit").click(function () {
var usrname = $("#username").val();
var pwd = $("#password").val();
$.post("http://localhost:50750/api/loginctrl/login",
{ username: usrname, password: pwd }, function (result) {
alert(JSON.stringify(result));
});
});
});
در پروژههای جدیدتر، استفاده از fetch یا axios انتخاب بهتری است. چون خوانایی و کنترل بیشتری ایجاد میکند.
ثبت Delegating Handler
برای فعال شدن Handler، باید آن را در شروع برنامه ثبت کنید. این کار معمولاً در Application_Start انجام میشود.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var basicAuthMessageHandler = new WebAPI_FormsAuth.Helper.BasicAuthMessageHandler();
basicAuthMessageHandler.PrincipalProvider =
new WebAPI_FormsAuth.Helper.adminPrincipalProvider();
GlobalConfiguration.Configuration.MessageHandlers.Add(basicAuthMessageHandler);
}
اگر این بخش بهدرستی ثبت نشود، احراز هویت در درخواستها عمل نخواهد کرد.
نکات مهم امنیتی
استفاده از اعتبارسنجی فرم توسط Web API بدون توجه به امنیت، میتواند مشکلساز شود. هرچند این روش هنوز کاربردی است، اما باید با دقت اجرا شود.
توصیههای ضروری
- 🛡️ همیشه از HTTPS استفاده کنید.
- 🛡️ اطلاعات حساس را در Session بدون محافظت نگه ندارید.
- 🛡️ برای رمز عبور، از هش امن استفاده کنید.
- 🛡️ زمان انقضای Session و Cookie را مدیریت کنید.
- 🛡️ خطاهای Login را عمومی نمایش دهید.
- 🛡️ برای جلوگیری از سوءاستفاده، Rate Limiting در نظر بگیرید.
مراحل ثبتنام بهصورت خلاصه
اگر میخواهید از سرویس مرتبط استفاده کنید، فرایند ثبتنام را ساده و کوتاه انجام دهید:
- ✍️ وارد صفحه ثبتنام شوید: p.api.ir
- 📩 اطلاعات اولیه مانند ایمیل و رمز عبور را وارد کنید.
- ✅ حساب خود را تأیید کنید.
- 🔑 پس از ورود، تنظیمات سرویس و دسترسیهای لازم را بررسی کنید.
این روند برای شروع استفاده از سرویس، سریع و ساده است.
چه زمانی بهتر است به Identity مهاجرت کنیم؟
اگر پروژه شما در حال توسعه است، بهتر است آیندهنگر باشید. Forms Authentication برای سیستمهای قدیمی مناسب است. اما برای پروژههای جدید، Identity و روشهای مدرن، امنیت و توسعهپذیری بیشتری دارند.
نشانههای زمان مهاجرت:
- افزایش تعداد کاربران
- نیاز به احراز هویت چندمرحلهای
- نیاز به مدیریت حرفهای رمز عبور
- اتصال به سرویسهای خارجی
- توسعه API برای چند کلاینت مختلف

