آموزش سفارشی کردن ASP.NET Identity و استفاده از MVC 5

چگونه ASP.NET Identity را سفارشی سازی کنیم ؟ با سلام خدمت شما دوستان در این مقاله قصد دارم تا آموزش Identity با شما با اشتراک بگذارم ، در این مقاله قصد دارم تا با هم نحوه استفاده و کاربر Identity در MVC 5 آشناشویم. نکته: دراین آموزش علاوه بر یادگیری Identity با ساخت فرم ثبت نام و ورود در یک صفحه و کمی هم با کدفرست آشنا خواهید شد. پس از خواندن مطلب پیشنهاد میشود پروژه ضمیمه شده همین مقاله هم نگاه کنید. یک توضیح کوتاه درباره Asp.Net Identity : سیستم membership هست که روی ASP.NET 4.5 فعال هستش و برای تعریف role ها و تخصیص آن به کاربران می باشد. ابتدا یک پروژه با نام دلخواه ایجاد می کنیم

دوره های شبکه، برنامه نویسی، مجازی سازی، امنیت، نفوذ و ... با برترین های ایران
سرفصل های این مطلب
  1. چند نکته مهم
ایجاد پروژه

همان طور که در تصور مشاهده می فرمایید، ما یک پروژه MVC خواهیم ساخت که ChangeAuthentication آن را روی No Authentication قرار می دهیم.پروژه ما ساخته شد! حالا نوبت به طراحی دیتابیس می رسد.ما به 2 جدول نیاز داریم ؛ جدول اول که برای ثبت نام و ورود از آن استفاده میکنیم (جدول Users) جدول دوم که برای تعریف نقش ها (نقش های کاربری مانند ادمین و..) با نام Roles

دامین مدل برای جدول کاربران

همان طور که مشاهده می فرمایید ما یک دامین مدل برای جدول User ساختیم و پراپرتی های مورد نیازمان را ساختیم.(توجه کنید که ما پراپرتی با نام UserName نساختیم زیرا ما ایمیل کاربر را نام کاربریش در نظر میگیرم.)

دامین مدل برای نقش ها

همچنین یک دامین مدل دیگری هم برای نقش ها ساختیم.نکته قابل توجه این است که RoleName نام نقش ما برای نمایش (مثلا ادمین)و RoleInSystem نام برای استفاده درAttribute ها و کار با نقش ها می باشد.(در ادامه کاملا متوجه خواهید شد)

جدول

این هم تعریف جداول ما حال ما باید ابتدا یک کلاس RoleProvider بسازیم:

ساخت کلاس provider

خوب همانطور که از تصویر مشخص است ما یک کلاس با نام دلخواه (اما با معنی!) انتخاب کردیم که از کلاس RoleProvider ارث بری کرده است و ما می بایست اعضایش را پیاده سازی کنیم:

پیاده سازی و کد نویسی اعضا

همان طور که میبینید با پیاده سازی عناصر متد هایی اضافه می شود که کاملا نام آنها گویای کاربر آن می باشد و در صورت نیاز می توانید آنها را پیاده سازی کنید.متدی که خیلی مهم می باشد متد string[] GetRolesForUser(string username) است همانطور که قبلا گفتم نام متدها گویای کاربردش می باشد ، نقشها را برای کاربر میگیرد. دقت کنید ! این متد یک ورودی رشته با نام username می گیرد و درست در همین متد می باشد که ما تعیین خواهیم کرد کدام پراپرتی به عنوان نام کاربری انتخاب شود. حال کمی در مورد کد های بالا توضیح خواهم داد:

ما یک کوئری بر روی جداول Users و Roles که قبلا با هم ساخته بوده ایم زدیم (join) و کاربری که RoleId آن با RoleId جدول Roles برابر است را پیدا می کنیم ، و یک شرط مهم قرار دادیم where u.UserMail == username ما با این شرط تعیین کردیم که ایمیل به عنوان نام کاربری انتخاب شود . شما می توانید با تغییر UserMail به هر پراپرتی در دامین مدل User آن پراپرتی را به عنوان نام کاربری انتخاب کنید ! به همین راحتی × اما در انتخاب پراپرتی مناسب دقت لازمه را مبذول فرمایید! و در آخر هم RoleInSystem را بر میگردانیم. این کار برای تمام کاربرها انجام میشود و در آخر به صورت آرایه رشته ای برگردانده می شود ، دقت کنید که من در بالای متد ها شی Context ساختم. خوب حالا کار دیگری هم مانده ؟ بله آخرین کار یعنی معرفی به فایل WebConfig

تنظیمات Webconfig

Authentication به معنای احراز هویت می باشد که بر روی Forms قرار داده ایم. در خط بعد ما یک نام قرار دادیم یک timeout زمانی می باشد که loginUrl آدرس صفحه ورود می باشد که کنترلر و اکشن ان را بعدا خواهیم ساخت و کاربرانی که بدون احراز هویت وارد صفحه محافظت شده ،شوند به طور خودکار وارد این صفحه خواهند شد defaultUrl آدرس صفحه می باشد که کاربر بعد از احراز هویت به طور خودکار وارد آنجا خواهد شد. رول منیجر Enable کرده و نام کلاس RoleProvider ای که ساختیم را معرفی خواهیم کرد. در آخرهم نام همان کلاس فراهم کننده که ساختیم و آدرس مکانی که آن کلاس در آن قرار دارد. تمام!

هرآنچه تا کنون انجام داده ایم پیاده سازی سفارشی asp.net Identity بودحال می خواهیم از asp.net Identity در پروژه استفاده کنیم: بگذارید ابتدا برای سایتمان صفحه ورود و عضویت درست کنیم هردو در یک صفحه × خوب این که هر دو را در یک صفحه پیاده کنیم یا خیر در روند کدنویسی فقطی ندارد پس شما اگر لازم داشتید به راحتی میتوانید صفحات را از هم جدا سازی کنید. خوب بریم سر اصل مطلب ابتدا یک کنترلر به نام Account می سازیم ، اما یک لحظه دست نگهدارد ! آیا می خواهید در صفحه عضویت کاربر تمام پراپرتی ها پر کند؟ ویا هنگام ورود کاربر به سایت تمام پراپرتی ها را درست پر کند ؟!(...درست کردن لیست بلند برایگرفتن تمام اطلاعات کاربر باعت ناراحتی و صرف زیاد وقت کاربر برای ثبت نام و وبود می شود...)

چه می شود اگر ما برای ثبت نام فقط نام کاربری و کلمه عبور بگیریم و هنگام ورود کاربر از سایت فقط هم اطلاعات را از کاربر بگیریم ؟ برای رفع این مشکل ما از ViewModel ها استفاده می کنیم ، درکل اگر بخواهم یک توضیح کوتاه دهم می توانم اینگونه بگویم که ViewModel ها برای ترکیب چند پراپرتی های چندمدل با هم یا گلچین کردن چند پراپرتی خاص می باشد. پس بیایید ابتدا 2 ViewModel درست کنیم اولی برای عضویت و دومی برای ورود برای ثبت نام Email و نام کاربر و Password را بگیریم کفایت می کند

Register ViewModel

یک کلاس با نام RegisterViewModel ساختیم و در آن پراپرتی هایی که برای ثبت نام لازم داریم را قرار داده ایم (بقیه مشخصات را می توانید در پروفایل یا موقع مثلا خرید از کاربر بگیرید) دقت کنید پراپرتی های ما باید حتما بدون غلط املایی و دقیقا همان پراپرتی های باشند که در دامین مدل User نوشته ایم. و حالا دامین مدل برای ورود کاربر به نام LoginViewModel

LoginViewModel

تصور گویای همه چیز می باشد و از توضیح اضافه خودداری میکنم. و حالا این شما و این کنترلر Account

AccountController

چون قرار هست هر دو صفحه ورود و عضویت با هم در یک صفحه باشد ما مدل های صفحاتمان را از طریق Viewbag به ویو پاس می دهیم در غیر این صورت بعدا با مشکل مواجه خواهیم شد.(اگر صفحات ورود-عضویت شما جدا هستند می توانید ویو را Strongly typed تعریف کنید به این معنا که ViewModel ها را مدل صفحه قرار دهید) خوب حالا برویم ویو را درست کنیم دو فرم برای ثبت نام و دیگری برای ورود می سازیم

Account View

چند نکته مهم

1- چون ویو ما مدل ندارد پس ما مدلی تعریف نکردیم (@model)

2- ما بجای تعریف مدل در ویو ما از ویوبگ ها استفاده کردیم از آنجایی که ویو بگ ها داینامیک هستند و Intlisens ندارند اما ابتدا ویوبگ ها را میگیریم و در متغییر می ریزیم و اینگونه است که Intlisinse دار میشوند !

3- چون ما @model ندارم پس از متغییر ها استفاده میکنیم

@Html.EditorFor(model => login.UserMail, new { htmlAttributes = new { @class = "form-control" } })

4- به دکمه های ورود توجه کنید

<input type="submit" value="ورود" class="btn btn-default" />

<input type="submit" value="ثبت نام" class="btn btn-default"/>

حالا بر میگریدم به کنترلر تا آن را تکمیل کنیم

تکمیل کنترلر Account

ما یک اکشن ساختیم که فقط Httppost میباشد با دو ورودی ، یک ورودی از جنس LoginViewModel و یک رشته که نام دکمه کلیک شده توسط کاربر را نمایش می دهد.در کنترلر چک میکنیم که اگر کاربر روی دکمه "ورود" کلیک کرده و مشخصات را پر کرده بود ، ابتدا کلمه عبور را میگیرم و رمزگذاری میکنیم (این نوع رمزنگاری یک طرفه می باشد و وفقط می توان رمز کرد-البته منسوخ شده نیز میباشد) بعد چک میکنیم اگر کاربری با ایمیل و کلمه عبور رمزگذاری شده در بانک اططلاعاتی ما وجود داشت کوکی مربوط به احرازهویست را ست کن و تیک مرابه خاطر بسپار را در آن قرار میدهیم و در آخر هم پس از احرازهویت به DefaultUrl ای که در Webconfig تنظیم نمیده ایم کاربر منتقل میشود.

تکمیل کنترلر Account

یک اکشن دیگر مانند قبلی میسازیم با این تفاوت که ورودی اول از جنس RegisterViewModel می باشد. اگر کاربر بر روی دکمه ثبت نام کلیک کرده بود اگر چنین کاربری وجود نداشت آن را می سازیم و نقش آن را 2 ( نقش کاربر) قرار دادیم ، خوب حالا بریم Migration را بسازیم تا در متد seed آن مقدار Role آن را مقدار دهی کنیم(مقدار آزمایشی) برای این کار با دستورات زیر migration را فعال می کنیم

Enable-Migrations
Migration Seed Method

من یک نقش ادمین ساختیم و یک نقش کاربر و دو کاربر با نقش های مختلف قبل از ادامه کار خوب است بدانید فرق authorize و authentication چیست؟ به غیر از تشابه املایی Authorize به معنای اجاز دادن می باشد ، Authentication به معنای احراز هویت ما احراز هویت را در بخش ورود و ثبت نام انجام داده ایم حال نوبت به اجازه دادن میرسد ، چه نقشی اجازه دارد به چه صفحه ای دسترسی داشته باشد! این کار در بخش کنترلر ها به راحتی تعریف یک صفت (attribute) می باشد به این صورت

قرار دادن صفت دسترسی

به همین راحتی ! زمانی که روی کنترلر صفت اعمال کنیم روی تمامی متد های این کلاس اعمال میشود و در صورتی که می خواهید روی متدی صفت خاصی قرار بدهید فقط کافیست تا در بالای آن متد صفت مورد نظر را بنویسید.

وب سایت توسینسو
  • [AllowAnonymous] همه کاربران دسترسی به اکشن/کنترلر مورد نظر را دارند
  • [Authorize] فقط کاربران احرازهویت شده دسترسی به اکشن/کنترلر مورد نظر را دارند
  • [Authorize(Roles = "Admin")] فقط کاربران احرازهویت شده دسترسی به اکشن/کنترلر مورد نظر را دارند که نقش آنها Admin باشد
  • [Authorize(Roles = "Admin , User")] مانند بالا می باشد فقط چند نقش را با هم تعریف کرده ایم

گاهی در کنترلر و اکشن ها لازم است که ما بدانیم آیا کاربر که قرار است از این اکشن استفاده کند احرازهویت شده است یا نه ؟ به عنوان مثال در همین کنترلر Account اگر کاربر احرازهویت شده بود نباید دوباره صفحه ورود و عضویت را ببیند . برای اینکار کافیست یک شرط را به ابتدای متد اضافه کنیم

وب سایت توسینسو

User :یک Iprincipal می باشد که کارش فقط گرفتن اطلاعات محرمانه کاربر از http request می باشد.User.IsInRole : یک یک نقش میگیرد و بررسی میکند که آیا کاربر این نقش را دارا میبباشد یا خیر

وب سایت توسینسو

کد بالا میگوید اگر کاربر وارد شده نقش ادمین را داشت وارد پنل ادمین شود در غیر این صورت وارد آدرس Home شود. User.Identity : Identity را از Iprincipal می گیرد.

اعضای Identity :

IsAuthenticated : بررسی می کند که آیا تصدیق هویت شده است یا خیر.

در کد بالا ما گفتیم اگر کاربر تصدیق هویت شده بود برو به home

حالا بگذارید به بقیه کد های Identity بپردازیم

IsAuthenticated که بالا تعریف کردیم

Name : این نام کاربری را برمیکرداند اگر بخاطر داشته باشید ما ایمیل را به عنوان نام کاربر قرار دادیم.

در مثال ما استفاده از این کد User.Identity.Name ایمیل را بر میگرداند

AuthenticationType : نوع احراز هویت را بر میگرداند که ما در webconfing آن را روی Form قرار داده ایم

جالب است نه ؟ حالا جلب ترهم خواهد شد

ما می توانید از همین کد هم سمت ویو استفاده کنیم!

 

استفاده از Identity  سمت view

ما در Webconfig نوع احرازهویت را روی Form قرار داده ایم، با این کار ما به کلاس FormsAuthentication درسترسی خواهیم داشت که این کلاس حاوی تعدادی متد و خواص مختلفی هست

وب سایت توسینسو

که شرح کامل آن زمان بر است اما با نگاه به عنوان و توضیحات متد ها کاملا کاربر آن مشخص می شود.

به عنوان مثال FormsAuthentication.SignOut(); این متد خروج کاربر از حساب کاربری را فراهم میکند !

 

و تمام.!

لینک دانلود پروژه

امیدوارم توانسته باشم کمی کمک کرده باشم


نظرات