AuthenticationHandler در مقابل AuthorizationHandler
AuthenticationHandler در ASP.NET Core مسئول تشخیص "کاربر کیست" است — اعتبارسنجی توکن/کوکی و ساخت ClaimsPrincipal از هویت درخواست؛ AuthorizationHandler مسئول تصمیمگیری "آیا این کاربر مجاز است" است — بررسی خطمشیها (Policy) و claim ها پس از احراز هویت برای اجازه یا رد دسترسی به یک منبع خاص.
| ویژگی | AuthenticationHandler | AuthorizationHandler |
|---|---|---|
| سوالی که پاسخ میدهد | کاربر کیست؟ | آیا کاربر مجاز است؟ |
| زمان اجرا در pipeline | قبل (احراز هویت) | بعد از احراز هویت |
| خروجی | ClaimsPrincipal | نتیجه Succeed/Fail برای یک Requirement |
| مثال کاربرد سفارشی | احراز هویت با API Key | بررسی مالکیت منبع |
کِی از AuthenticationHandler استفاده کنیم؟
وقتی میخواهید یک مکانیزم سفارشی برای شناسایی کاربر پیاده کنید (مثلاً یک روش احراز هویت غیراستاندارد بر پایه هدر API Key)، یک AuthenticationHandler سفارشی بنویسید که از AuthenticationHandler
کِی از AuthorizationHandler استفاده کنیم؟
وقتی منطق مجوزدهی شما فراتر از نقشهای ساده است (مثلاً "فقط مالک منبع یا ادمین اجازه ویرایش دارد")، یک AuthorizationHandler سفارشی برای یک Requirement خاص بنویسید و آن را به Policy اضافه کنید.
مثال AuthenticationHandler
public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyOptions>
{
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.TryGetValue("X-Api-Key", out var key))
return Task.FromResult(AuthenticateResult.Fail("Missing API Key"));
var identity = new ClaimsIdentity("ApiKey");
return Task.FromResult(AuthenticateResult.Success(
new AuthenticationTicket(new ClaimsPrincipal(identity), Scheme.Name)));
}
}
مثال AuthorizationHandler
public class OwnerRequirementHandler : AuthorizationHandler<OwnerRequirement, Order>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context, OwnerRequirement req, Order order)
{
if (order.OwnerId == context.User.GetUserId())
context.Succeed(req);
return Task.CompletedTask;
}
}
اشتباه رایج
نوشتن منطق مجوزدهی پیچیده (مثل بررسی مالکیت منبع) داخل خود AuthenticationHandler، در حالی که این مسئولیت باید کاملاً جدا و در یک AuthorizationHandler انجام شود — ترکیب این دو مسئولیت، کد را غیرقابلتست و شکننده میکند.
جمعبندی
"این کاربر کیست؟" → AuthenticationHandler؛ "آیا این کاربر اجازه دارد؟" → AuthorizationHandler — همیشه این دو مسئولیت را جدا نگه دارید.
