آموزش احراز هویت user identity بخش اول
در این مقاله قصد داریم گام به گام مراحل ایجاد و کار با روش احراز هویت user identity را بررسی کنیم. با ما همراه باشید تا به سادگی یک برنامه بر این پایه ایجاد نمایید.
با سلام احراز هويت user identity به عقيده اکثر برنامه نويسان بسيار گيج کننده و پيچيده است اما نظر من متفاوت است و به نظر من اين ساختار بسيار ساده جذاب و روان است و قطعا مي تواند کمک هاي بسياري به شما بکند و ويژگي هاي بسياري به برنامه شما بيفزايد.
با ما همراه باشيد تا بعد از گذراندن 33 گام ساده و واضح يک برنامه به پايه user identity داشته باشيد.
در اين مقاله قصد داريم به صورت ساده تنها به پياده سازي ساختار بدون استفاده از ديتابيس بپردازيم تا سادگي و روان بودن آموزش ملموس تر شود. در مقاله بعدي نيز به طور کامل پايگاه داده را وارد برنامه ميکنيم تا آموزش کامل شود.
قبل از شروع بايد بگم کسي که شروع به کار با asp.net user identity ميکنه حتما يه آشنايي با برنامه نويسي Asp.net mvc داره و پيش فرض ما در آموزش اين هست و از توضيحات اضافه پرهيز ميکنيم تا حجم مقاله خيلي زياد نشود.
خب بيايد شروع کنيم:
1)ابتدا يک پروژه خالي mvc ايجاد کنيد. يک پروژه empty با ساختار mvc
2)از طريق نوگت پکيج زير را نصب:
PM > Install-Package Microsoft.Owin.Host.SystemWeb
3)همچنين چون ميخواهيم بر پايه کوکي احراز هويت کنيم پکيج زير را نيز نصب نماييد:
PM > Install-Package Microsoft.Owin.Security.Cookies
4) بر روي پروژه راست کليک و گزينه add-> Owin Startup Class را ميزنيم.
5) کلاس را با نام Startup ايجاد کنيد.
6) کد زير را داخل متد configuration کلاس مرحله 5 قرار ميدهيم:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "ApplicationCookie",
LoginPath = new PathString("/Account/Login")
});
7) UseCookieAuthentication به برنامه ميگويد ميخواهيم بر پايه cookie احراز هويت را انجام دهيم.
8) LoginPath مسيري که اگر کاربر غير مجاز بود به آنجا Redirect گردد. (ميتوانيد براي خود شخصي سازي نماييد.)
9) يک پوشه به نام Filter ايجاد کنيد و يک کلاس به نام FilterConfig به آن اضافه نماييد(فيلترها براي انجام اعمالي قبل از اجراي اکشن ها استفاده ميشوند و ما ميخواهيم از فيلتر براي احراز هويت بهره ببريم). سپس متد زير را درون کلاس قرار دهيد:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new AuthorizeAttribute());
}
10) در global.asax.cs تکه کد زير را در انتهاي تابع Application_Start() قرار ميدهيم تا فيلتر اعمال گردد:
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
11) کنترلر Home را ايجاد کنيد.
12) View متد index را اضافه ميکنيم.
13) کنترلر Account را براي احراز هويت کاربران ايجاد کنيد و در بالاي کنترلر از attribute ، [AllowAnonymous] استفاده کنيد تا اين بخش براي احراض هويت همه قابل دسترس باشد. پس کنترلر ما به صورت زير خواهد شد:
[AllowAnonymous]
public class AccountController : Controller
{
public ActionResult Login()
{
return View();
}
}
14) View مربوط به متد مربوط به متد Login را ايجاد ميکنيم.
15) حال پروژه را اجرا کنيد ميبينيد که به جاي Home/Index يا / به Account/Login ارسال ميشويد.
16) کلا هر کنترلري که بسازيد بر پايه احراز هويت خواهد بود. هنگاميکه بخواهيد بعضي از کنترلرهاي يا اکشن هاي شما نياز به احراز هويت نداشته باشند کافي است [AllowAnonymous] را به بالاي کنترلر يا اکشن مورد نظر اضافه کنيد تا اجازه دسترسي داده شود.
17) در پوشه Models يک پوشه به نام ViewModels ايجاد و سپس يک کلاس به نام Login ايجاد ميکنيم و آن را به صورت زير در مي آوريم:
public class Login
{
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[HiddenInput]
public string ReturnUrl { get; set; }
}
18) حال اکشن Login را به صورت زير تغيير دهيد:
[HttpGet]
public ActionResult LogIn(string returnUrl)
{
var model = new Models.ViewModels.Login
{
ReturnUrl = returnUrl
};
return View(model);
}
19) حال دو تابع زير را به کنترلر Account اضافه ميکنيم که اولي براي post لاگين است و دومي براي Redirect کردن به صفحه اوليه.
[HttpPost]
public ActionResult LogIn(Models.ViewModels.Login model)
{
if (!ModelState.IsValid)
{
return View();
}
// Don't do this in production!
if (model.Email == "[email protected]" && model.Password == "password")
{
var identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name, "Ben"),
new Claim(ClaimTypes.Email, "[email protected]"),
new Claim(ClaimTypes.Country, "England")
},
"ApplicationCookie");
var ctx = Request.GetOwinContext();
var authManager = ctx.Authentication;
authManager.SignIn(identity);
return Redirect(GetRedirectUrl(model.ReturnUrl));
}
// user authN failed
ModelState.AddModelError("", "Invalid email or password");
return View();
}
private string GetRedirectUrl(string returnUrl)
{
if (string.IsNullOrEmpty(returnUrl) || !Url.IsLocalUrl(returnUrl))
{
return Url.Action("index", "home");
}
return returnUrl;
}
20) به Login.cshtml برويد و کد آن را به صورت زير تغيير دهيد:
@model user_identity.Models.ViewModels.Login
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
@section header{
<title>ورود</title>
}
<h2>ورود</h2>
<h2>Log In</h2>
@Html.ValidationSummary(true)
@using (Html.BeginForm())
{
@Html.EditorForModel()
<p>
<button type="submit">ورود</button>
</p>
}
21) حال اگر با ([email protected]/password) ورود کنيد به صفحه خانه بازگشت داده ميشويد براي اينکه از ورود اطمينان حاصل کيند تکه کد زير را به view اصلي home اضافه کنيد تا نام کاربر را نمايش دهد.
<p>
Hello @User.Identity.Name
</p>
22) حال براي خروج کاربر تابع زير را به کنترلر Account اضافه کنيد.
public ActionResult LogOut()
{
var ctx = Request.GetOwinContext();
var authManager = ctx.Authentication;
authManager.SignOut("ApplicationCookie");
return RedirectToAction("Index", "Home");
}
23) سپس تکه کد زير را به View اصلي home اضافه کنيد تا دکمه خروج ايجاد شود:
<p>
<a href="@Url.Action("logout", "Account")">خروج</a>
</p>
24) در حال حاضر ما تنها امکان دسترسي به نام کاربر جاري را داريم که نمايش داديم اما براي دسترسي به بقيه موارد اطلاعات کاربر نياز است تا اکشن index در Home را به صورت زير بازنويسي کنيم:
var claimsIdentity = User.Identity as ClaimsIdentity;
ViewBag.Country = claimsIdentity.FindFirst(ClaimTypes.Country).Value;
که در آن user.Identity را به ClaimsIdentity تبديل نموده ايم تا با استفاده از خواص آن به مقاديري که قبلا مقدار داده ايم دسترسي داشته باشيم که در اينجا نما کشور است.
25) حال براي نمايش نام کشور کاربر جاري تکه کد زير را به view ، index کنترلر Home اضافه ميکنيم :
<p>
سلام @User.Identity.Name. هواي @ViewBag.Country چطوره?
</p>
26) راه بهتر براي کار بالا به اين صورت است: ابتدا يک پوشه به نام Identity ايجاد کنيد و درون آن يک کلاس با نام AppUser ايجاد کنيد و محتواي آن را به صورت زير قرار دهيد:
public class AppUser : ClaimsPrincipal
{
public AppUser(ClaimsPrincipal principal)
: base(principal)
{
}
public string Name
{
get
{
return this.FindFirst(ClaimTypes.Name).Value;
}
}
public string Country
{
get
{
return this.FindFirst(ClaimTypes.Country).Value;
}
}
}
اين کلاس از ClaimsPrincipal ارث ميبرد و با اين کلاس دو خاصيت نام و کشور را ايجاد که بعدا براي ما قابل دسترسي باشد.
27) سپس يک کنترلر جديد با نام BaseController ايجاد ميکنيم و درون آن يک ويژگي CurrentUser که از نوع کلاس AppUser مرحله قبل است ايجاد ميکنيم.
public abstract class BaseController : Controller
{
public AppUser CurrentUser
{
get
{
return new AppUser(this.User as ClaimsPrincipal);
}
}
}
سپس در کنترلر هاي AllowAnonymousController و HomeController از اين کنترلر جديد ارث ميبريم در واقع همه کنترلرهاي بايد هميشه از اين کنترلر ارث ببرند تا اطلاعات کاربر درون آن باشد.
28) حال بايد متد index درون کنترلر home را به صورت زير در آوريم
public ActionResult Index()
{
ViewBag.Country = CurrentUser.Country;
return View();
}
که در آن CurrentUser ، Property همان کنترلر base است که در همه جا وجود دارد و قبلا آن را با کلاس AppUser پر نموديم .
29) ميخواهيم کار را بهتر کنيم و ديگر از viewbag هم استفاده نکنيم. خب ابتدا در پوشه identity يک کلاس به نام AppViewPage بسازيد و سپس آن را به صورت زير بازنويسي کنيد:
public abstract class AppViewPage : WebViewPage
{
protected AppUser CurrentUser
{
get
{
return new AppUser(this.User as ClaimsPrincipal);
}
}
}
public abstract class AppViewPage : AppViewPage
{
}
30) حالا به web.config داخل پوشه view برويد و تگ page در درون تگ
<pages pageBaseType="user_identity.Identity.AppViewPage">
31) حال به view اصلي home برويد محتواي زير را جايگزين محتوايي کنيد که در مرحله 25 اضافه کرده بوديم:
<p>
سلام @CurrentUser.Name. هواي @CurrentUser.Country چطوره?
</p>
32) حال کد هاي اضافه را از اکشن index در home پاک کرده به به شکل زير در آورديد:
public ActionResult Index()
{
return View();
}
33) کار تمام است. برنامه را اجرا کنيد و از احراز هويت بر پايه user identity لذت ببريد.
به نظرم حالا شما هم، هم عقيده من شده ايد که اين ساختار نه تنها پيچيده نيست اتفاقا خيلي ساده و جذاب ميباشد.
حالا بهتره بعد از يه استراحت کوچيک بريم به سراغ مقاله بعدي ما که پياده سازي user identity به همراه ديتا بيس خواهد بود. مطمئن باشيد اون هم مثل اين بخش خيلي ساده هست و فقط نياز به حضور ذهني شما دارد.