صفت Authorize در MVC

دوشنبه 19 بهمن 1394

در این مقاله قصد داریم مجوزدهی در MVC را به همراه RoleProvider و در نهایت سفارشی سازی صفت Authorize به صورتی که از ما پارامتری از نوع Enum بپذیرد را آموزش دهیم .

 صفت Authorize در MVC

صفت Authorize  جهت بررسی مجوزهای کاربر به کار می رود .بعد از اینکه کاربر به برنامه لاگین شد (در واقع احراز هویت  یا همان Athentication شد ) باید بررسی کنیم که آیا مجوز دیدن صفحات ما را دارد یا نه

در برنامه های Asp.net برای اینکه مفهوم مجوز را پیاده سازی کنیم ، صفحاتی که کاربران عادی نباید می دیدند در یک قسمت جداگانه قرار می دادیم و بعد در web.config تغییراتی را ایجاد می کردیم .تا هر کسی که می خواست این صفحات خاص را ببیند به صفحه لاگین هدایت شود .

اما در MVC به راحتی می توانیم از صفت ها برای این منظور استفاده کنیم .صفت Authorize به همین منظور استفاده می شود .در این مقاله قصد داریم ابتدا Authorize  ساده و پس از آن RoleProvider و در نهایت Authorize سفارشی را توضیح داده و به صورت عملی پیاده سازی می کنیم .

صفت Authorize

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

ابتدا یک پروژه mvc از نوع empty ایجاد می کنیم .در داخل پایگاه داده یک دیتابیسی با سه جدول به نام های User ,role,News ایجاد می کنیم .شکل جداول به صورت زیر خواهد بود .

بعد از این کار مدل خود را از روی این جدول ایجاد می کنیم .یعنی توسط Entity  یک مدل از نوع این دیتابیس خود ایجاد می کنیم .بعد از این کار در داخل همان پوشه مدل خود یک کلاس دیگر به نام AccountViewModel ایجاد می کنیم .در داخل این کلاس namespase آن را حذف می کنیم .هدف ما این بود که در یک جا به صورت متمرکز کلاس های viewModel خود را ایجاد کنیم .در داخل این پوشه کلاس های RegisterViewModel برای ساخت view مربوط به ثبت نام کاربر ، کلاس LoginViewModel برای ساخت صفحه لاگین کاربر ، کلاس ForgotPassViewModel برای ساخت صفحه view مربوط به فراموش کردن پسورد کاربر ، کلاس ForgotPassViewModel برای ریکاوری کردن پسورد کاربر ، کلاس ChangePassViewModel برای ایجاد صفحه تغییر رمز کاربر ایجاد شده است .

 بعد از این کار یک کنترلر به نام Account ایجاد می کنیم .در داخل این کنترلر کارهای مربوط به لاگین کار بر را انجام می دهیم .اولین کاری که در داخل این کنترلر انجام می دهیم ثبت نام کاربر است این کار را با اکشن های زیر انجام می دهیم .دقت کنید که از کلاس registerviewModel برای ساخت ویو استفاده کرده ایم

     public ActionResult Register(RegisterViewModel register)
        {
            if (this.IsCaptchaValid("Captcha is not valid"))
            {
                if (ModelState.IsValid)
                {
                    if (!db.Users.Any(u => u.Email == register.Email.Trim().ToLower()))
                    {
                        User user = new User()
                        {
                            Email = register.Email.Trim().ToLower(),
                            Password = FormsAuthentication.HashPasswordForStoringInConfigFile(register.Password, "MD5"),
                            RegisterDate = DateTime.Now,
                            RoleID = 2,
                            UserName = register.UserName
                        };
                        db.Users.Add(user);
                        db.SaveChanges();
                        string body = PartialToStringClass.RenderPartialView("SendMails", "ActiveUser", user);
                        SendEmailGmail.Send(user.Email, "ایمیل فعال سازی", body);
                    }
                    else
                    {
                        ModelState.AddModelError("Email", "ایمیل وارد شده تکراری است");
                    }
                }
                else
                {
                    ModelState.AddModelError("CaptchaInputText", "Captcha is not valid");
                    return PartialView(register);
                }
            }
            return View(register);
        }

بعد از اینکه کاربران در سایت ثبت نام کردند از قصد داریم از سیستم احراز هویت استفاده کنیم . برای اینکه مثلا به صفحه news/index فقط کاربرانی که ثبت نام کرده اند دسترسی داشته باشند در داخل web.config تنظیمات زیر را انجام میدهیم .

<system.web>

    <authentication mode="Forms">

      <forms name="meRoleProvider" defaultUrl="/" loginUrl="/Account/Login" timeout="43200" />

    </authentication>

 

این تنظیمات باعث خواهد شد که بعد از احراز هویت توسط IIS (اگر IP ایی را غیر مجاز اعلام کرده باشیم توسط IIS احراز هویت می شودو اجازه دسترسی به سایت ما داده نخواهد شد)در ادامه این درخواست توسط IIS به ASP.net تحویل داده خواهد شد .حال در اینجا با توجه به نحوه پیکربندی روش مناسب اتخاذ خواهد شد .asp.net از سه روش برای احراز هویت استفاده می کند .Form، windows و Microsoft Passport .همان طور که دیدید ما طبق کد بالا از روش Form استفاده کردیم .

 

در داخل کنترلر News و در بالای Action به نام Create صفت [authorize] را می نویسیم .بنابراین اگر کاربر در داخل مرورگر آدرس صفحه Create از کنترلر News را بزند به صورت خود کار به صفحه لاگین هدایت خواهد شد .

استفاده از Role Provider

برای اینکه صفت authorize خود را نقش بدهیم و تعیین کنیم که به یک اکشن خاص فقط کاربرانی که دارای نقش Admin هستند دسترسی داشته باشند به صورت زیر عمل می کنیم .در داخل پوشه classes یک کلاسی به نام MyRoleProvider ایجاد می کنیم .این کلاس از کلاس RoleProvider ارث بری می کند .در داخل کلاس متدهای virtual کلاس RoelProvider را دوباری نویسی می کنیم .متدی که در اینجا برای ما مهم است متد GetRolesForUser است .به کد این تابع که در زیر نوشته شده است دقت کنید

 

 public override string[] GetRolesForUser(string username)

        {

            using (Myauthorize.Models.RoleProviderEntities db = new Myauthorize.Models.RoleProviderEntities())

            {

                return db.Users.Where(u=>u.UserName==username).Include(u => u.Role).Select(s => s.Role.RoleName).ToArray();

            }

        }

توسط این کد برای یک کاربر خاص نقش آن را به دست آورده ایم بنابراین اگر بالای متد مقلا create از کنترلر news صفت [Authorize(role=”Admin”)] تنها کاربرانی که ثبت نام شده باشند و نقش Admin داشته باشند می توانند از این اکشن استفاده کنند و صفحه view آن را مشاهده کنند .

[Authorize]

        [Authorize(Roles="admin")]


        public ActionResult Create()

        {

            ViewBag.NewsID = new SelectList(db.Users, "UserID", "UserName");

            return View();

        }

 

البته برای اینکه roleProvider ما کار کند باید در داخل web.config تنظیمات زیر را انجام دهیم .

 

<roleManager enabled="true" defaultProvider="MyRoleProvider">

      <providers>

        <clear />

        <add name="MyRoleProvider" type="Myauthorize.Classes.MyRoleProvider" />

      </providers>

    </roleManager>

 

تا به اینجای کار شما از سیستم مجوز دهی و roleprovider استفاده کردید .اگر در پروژه خود Area خاصی داشتید و برای کل ناحیه می خواستید که تعیین کنید فقط کاربر با نقش Admin بتواند وارد شود باز هم در web.config تنظیمات زیر را وارد کنید

 

<location path="admin">

    <system.web>

      <authorization>

        <allow roles="admin" />

        <deny users="*" />

      </authorization>

    </system.web>

  </location>

 

Authorize سفارشی شده

 

قصد داریم در یک پروژه دیگری که در داخل همین Solution اضافه کرده ایم به سفارشی سازی صفت Authorize بپردازیم .برای این کار یک پروژه دیگر از نوع mvc به solution خود اضافه می کنیم .

در این قسمت می خواهیم صفت Authorize خود را طوری سفارشی کنیم که برای role قابلیت پذیرش Enum از ما را داشته باشد .

ابتدا یک Enum به نام Role تعریف می کنیم .در داخل این Enum نقش هایی که در سیستم داریم را تعریف می کنیم .

 

 public enum Role

    {

        Administrator = 1,

        UserWithPrivileges = 2,

        User = 3,

    }

بعد از این کار یک کلاس به نام AuthorizeEnumAttribute را تعریف می کنیم .این کلاس از کلاس AuthorizeAttribute ارث بری دارد .

کدهای این کلاس به صورت زیر است .

AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]

    public class AuthorizeEnumAttribute : AuthorizeAttribute

    {

        public AuthorizeEnumAttribute(params object[] roles)

        {

            if (roles.Any(r => r.GetType().BaseType != typeof(Enum)))

                throw new ArgumentException("roles");


            this.Roles = string.Join(",", roles.Select(r => Enum.GetName(r.GetType(), r)));

        }

    }

در داخل کنترلر Home و برای اکشن ThePrivilegeZone کدهای زیر را می نویسیم

///    [AuthorizeEnum(Role.Administrator, Role.UserWithPrivileges)]

        public ActionResult ThePrivilegeZone()

        {

            return View();

        }

این کار باعث میشود که در هنگامی که آدرس این اکشن را در url تایپ می کنیم برنامه با استفاده از کلاس AuthorizeEnum و پارامترهایی که به آن پاس داده شده است تشخیص دهد که چه کاربرانی حق دسترسی به این اکشن را دارند .توجه داشته باشید که این پروژه را با کلیک راست کردن بر روی آن به حالت پیش فرض برای اجرا در آورده ایم .

اگر برنامه را اجرا کنید صفحه Home آن مانند زیر است .

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

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

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

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید