این روش به دلیل عدم وجود ذخیره کوکی، ایجاد Session و دیگر مباحث امنیتی، جز سادهترین روشهای تشخیص هویت میباشد و همچنین مشخص است به دلیل رمزگذاری سادهای چون Base64 و همچنین در صورت ارسال از طریق http نه https، حفاظت چندانی در ارسال الزامات امنیتی ندارند. ولی عموما برای گوشیهای همراه تا حد زیادی قابل قبول است. همچنین در این روش مکانیزم logout فراهم نیست و تنها در طی یک درخواست پردازش اطلاعات انجام شده و بعد از آن هویت شما نابود خواهد شد.
برای ارسال اطلاعات در هدر درخواستی، به شیوه زیر اطلاعات را ارسال میکنیم:
Authorization: Basic Username:Password
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
public class BasicAuthetication:AuthorizationFilterAttribute { public override void OnAuthorization(HttpActionContext actionContext) { if (actionContext.Request.Headers.Authorization == null) { SayYouAreUnAuthorize(actionContext); return; } var param = actionContext.Request.Headers.Authorization.Parameter; var decodedCridential = Encoding.UTF8.GetString(Convert.FromBase64String(param)); var splitedArray = decodedCridential.Split(':'); if (splitedArray[0] == "username" && splitedArray[1] == "password") { var userId = 1; var genericIdentity=new GenericIdentity(userId.ToString()); var genericPrincipal=new GenericPrincipal(genericIdentity,null); Thread.CurrentPrincipal = genericPrincipal; return; } SayYouAreUnAuthorize(actionContext); } private void SayYouAreUnAuthorize(HttpActionContext actionContext) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized); } }
در اولین خط از کد بررسی میشود که خاصیت Authorization در هدر درخواست وجود دارد یا خیر؛ در صورت که وجود نداشته باشد متد SayYouAreUnAuthorize صدا زده میشود. این متد وظیفه دارد، در صورتیکه صحت نام کاربری و کلمه عبور تایید نشد، خطای مورد نظر را که با کد 401 شناخته میشود، بازگرداند که در متد اصلی دو بار مورد استفاده قرار گرفته است. با استفاده از این بازگردانی و دادن پاسخ کاربر، دیگر api مورد نظر به مرحله اجرا نمیرسد.
در صورتیکه کد ادامه پیدا کند، مقدار تنظیم شده Authorization را دریافت کرده و در خط بعدی آن را از حالت انکود شده خارج میکنیم. از آنجاکه الگوی ارسالی ما به شکل username:password میباشد، با استفاده از متد الحاقی Split هر دو عبارت را جدا کرده و در خط بعد، صحت آن دو را مشخص میکنیم. از آنجا که این تکه کد تنها یک تست است، من آن را به شکل ساده و استاتیک نوشتهام. بدیهی است که در یک مثال واقعی، این تایید صحت توسط یک منبع داده انجام میشود. در صورتی که صحت آن تایید نشود مجددا متد SayYouAreUnAuthorize مورد استفاده قرار میگیرد. در غیر این صورت باید این تایید هویت را در ترد جاری تایید کرده و حفظ کنیم و حتی در صورت لزوم Id کاربر و نقشهای آن را ذخیره کنیم تا اگر api مورد نظر بر اساس آن تصمیم میگیرد، آنها را در اختیار داشته باشیم. به عنوان مثال ممکن است اطلاعات دریافتی پرداختیهای یک کاربر باشد که به UserId نیاز است.
از آنجا که در این روش نه ذخیره session و نه کوکی و نه مورد دیگری داریم و قصد داریم تنها در ترد یا درخواست جاری این اعتبار را نگه داریم، میتوانیم از thread.CurrentPrincipal استفاده کنیم. این خصوصیت نوع GenericPrincipal را نیاز دارد که دو پارامتر GenereicIdentity و آرایهای از نوع رشته را دریافت میکنید. این آرایهها متعلق به زمانی است که شما قصد دارید نقشهای یک کاربر را ارسال کنید و شیء GenericIdentity شیءایی است که شامل اطلاعات Authorization بوده و هیچ وابستگی به windows Domain ندارد. این شیء از شما تنها یک نام را به صورت رشته میگیرد که میتوانیم از طریق آن UserId را پاس کنیم. برای دریافت آن نیز داریم:
var userId=int.Parse(Thread.CurrentPrincipal.Identity.Name);
[BasicAuthetication] public HttpResponseMessage GetPayments(int type) { var userId = int.Parse(Thread.CurrentPrincipal.Identity.Name); if (type == 1) { return Request.CreateResponse(HttpStatusCode.OK, new { Id = 4, Price = 20000, userId=userId }); } return Request.CreateResponse(HttpStatusCode.OK, new { Id = 3, Price = 10000, userId = userId }); }
در api بالا attribute مدنظر بر روی آن اعمال شده و تنها مقادیر ورودی این api همان پارامترهای درخواست اصلی میباشد و ویژگی BasicAuthentication کدهای اعتبارسنجی را از کد اصلی دور نگه داشته است و api اصلی هیچگاه متوجه قضیه نمیشود و تنها کار اصلی خود را انجام میدهد. همچین در اینجا از طریق کلاس thread به UserId دسترسی داریم.
حال تنها لازم است کلاینت، قسمت هدر را پر کرده و آن را به سمت سرور ارسال کند. در اینجا من از نرم افزار I'm only resting استفاده میکنیم تا درخواست رسیده را در WebApi تست نمایم.