تعیین دسترسی کاربران بر اساس نقش ها در MVC

پنجشنبه 18 تیر 1394

در این مقاله به نحوه دسترسی صفحه login براساس نقش ها در mvc می پردازیم.

تعیین دسترسی کاربران بر اساس نقش ها در MVC

در این مقاله قصد داریم که یک سیستم مدیریت سطح دسترسی کاربران در صفحه Login براساس نقش ها تعیین کنیم. به عنوان مثال یک سیستم دارای صفحات مختلفی است که هر گروه کاربری اجازه دسترسی به هر صفحه را ندارد و هدف این است که گروه های کاربری و سطح دسترسی برای هر گروه را برای سیستم مشخص کنیم که مثلا admin بتواند بعد از login شدن به صفحه مدیریتی خود دسترسی داشته باشد.

در مرحله اول باید بانک اطلاعاتی را بسازیم و اطلاعات را در آن وارد کنیم. به عنوان مثال سه جدول زیر را مشاهده کنید:

یک روش دیگر برای ایجاد جدول که اگر حال ساختن جدول را ندارید می توانید دستورات Query زیر را در SQL اجرا کنید:

CREATE TABLE [dbo].[Roles](  
[RoleID] [int] IDENTITY(1,1) NOT NULL,  
[ROleName] [varchar](50) NOT NULL,  
PRIMARY KEY CLUSTERED  
(  
[RoleID] ASC  
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]  
) ON [PRIMARY]  
GO  
SET ANSI_PADDING OFF  
GO  
/****** Object: Table [dbo].[UserRoles] Script Date: 7/4/2015 5:55:16 PM ******/  
SET ANSI_NULLS ON  
GO  
SET QUOTED_IDENTIFIER ON  
GO  
CREATE TABLE [dbo].[UserRoles](  
[UserRolesID] [int] IDENTITY(1,1) NOT NULL,  
[RoleID] [int] NOT NULL,  
[UserID] [int] NOT NULL,  
PRIMARY KEY CLUSTERED  
(  
[UserRolesID] ASC  
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]  
) ON [PRIMARY]  
GO  
/****** Object: Table [dbo].[Users] Script Date: 7/4/2015 5:55:16 PM ******/  
SET ANSI_NULLS ON  
GO  
SET QUOTED_IDENTIFIER ON  
GO  
SET ANSI_PADDING ON  
GO  
CREATE TABLE [dbo].[Users](  
[UserID] [int] IDENTITY(1,1) NOT NULL,  
[Username] [varchar](50) NOT NULL,  
[Password] [varchar](50) NOT NULL,  
[FirstName] [varchar](50) NOT NULL,  
[LastName] [varchar](50) NULL,  
[EmailID] [varchar](200) NULL,  
PRIMARY KEY CLUSTERED  
(  
[UserID] ASC  
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]  
) ON [PRIMARY]  
GO  
SET ANSI_PADDING OFF  
GO  
SET IDENTITY_INSERT [dbo].[Roles] ON  
GO  
INSERT [dbo].[Roles] ([RoleID], [ROleName]) VALUES (1, N'Admin')  
GO  
INSERT [dbo].[Roles] ([RoleID], [ROleName]) VALUES (2, N'User')  
GO  
SET IDENTITY_INSERT [dbo].[Roles] OFF  
GO  
SET IDENTITY_INSERT [dbo].[UserRoles] ON  
GO  
INSERT [dbo].[UserRoles] ([UserRolesID], [RoleID], [UserID]) VALUES (1, 1, 1)  
GO  
INSERT [dbo].[UserRoles] ([UserRolesID], [RoleID], [UserID]) VALUES (2, 2, 2)  
GO  
SET IDENTITY_INSERT [dbo].[UserRoles] OFF  
GO  
SET IDENTITY_INSERT [dbo].[Users] ON  
GO  
INSERT [dbo].[Users] ([UserID], [Username], [Password], [FirstName], [LastName], [EmailID]) VALUES (1, N'knk', N'knk', N'sample', N'sample1', N'sample@gmail.com')  
GO  
INSERT [dbo].[Users] ([UserID], [Username], [Password], [FirstName], [LastName], [EmailID]) VALUES (2, N'kumar', N'kumar', N'run', N'ran', N'kumar@gmail.com')  
GO  
SET IDENTITY_INSERT [dbo].[Users] OFF  
GO 

مرحله دوم : ایجاد یک پروژه وب سایت

ویژوال استودیو (Visual Studio) را باز کنید. به منوی فایل رفته،سپس گزینه NewProject -->ASP.Net Web Application--> یک نام پروژه در آن انتخاب کنید --> گزینه Empty -->MVC را انتخاب کنید.

مرحله سوم : اضافه کردن یک مدل (model)

دستورات کد زیر را در کلاسی که بالا به نام login ایجاد کردیم (login.cs) اضافه کنید.

using System;  
using System.Collections.Generic;  
using System.ComponentModel.DataAnnotations;  
using System.Linq;  
using System.Web;  
namespace MvcApplication2.Models {  
    public class login {  
        [Required(ErrorMessage = "Username required.", AllowEmptyStrings = false)]  
        public string Username {  
            get;  
            set;  
        }  
        [Required(ErrorMessage = "Password required.", AllowEmptyStrings = false)]  
        [DataType(System.ComponentModel.DataAnnotations.DataType.Password)]  
        public string Password {  
            get;  
            set;  
        }  
        public bool RememberMe {  
            get;  
            set;  
        }  
    }  
} 

مرحله چهارم : اضافه کردن یک کنترلر(Controller)

حالا دستورات کد زیر را در صفحه Home Controller که در بالا ایجاد کردید، اضافه کنید :

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Mvc;  
  
namespace MvcAuthentication.Controllers {  
    public class HomeController: Controller {  
        [AllowAnonymous] //This is for Un-Authorize User  
        public ActionResult Index() {  
            return View();  
        }  
  
        [Authorize] // This is for Authorize user  
        public ActionResult MyProfile() {  
            return View();  
        }  
  
        [Authorize(Roles = "Admin")]  
        public ActionResult AdminIndex() {  
            return View();  
        }  
  
        [Authorize(Roles = "User")]  
        public ActionResult UserIndex() {  
            return View();  
        }  
  
    }  
} 

مرحله پنجم : اضافه کردن View

بعد از add view در بالا یک صفحه html به نام Index.cshtml ایجاد می شود که دستورات زیر را در آن اضافه کنید.

@{  
   ViewBag.Title = "Index";  
}  
<h2>Index</h2>  
<h3>Welcome Guest - This is for all the anonymous user</h3>  
Myprofile.cshtml  
@{  
   ViewBag.Title = "MyProfile";  
}  
<h2>My Profile</h2>  
<h3>Welcome @(Request.IsAuthenticated ? HttpContext.Current.User.Identity.Name : "Guest") - This is for Authorized user </h3>

همچنین برای سایر اکشن ها (Action) به همین روال بالا یک view اضافه کرده و دستورات مربوط به آن ها را در صفحه html اضافه کنید.

صفحه Userindex.cshtml :

@{  
   ViewBag.Title = "UserIndex";  
}  
<h2>User Index</h2>  
<div>Welcome @(Request.IsAuthenticated? HttpContext.Current.User.Identity.Name : "") (User) </div>

صفحه Admin.cshtml :

@{  
   ViewBag.Title = "AdminIndex";  
}  
<h2>Admin Index</h2>  
   <div>Welcome @(Request.IsAuthenticated? HttpContext.Current.User.Identity.Name : "") (Admin)</div> 

مرحله ششم : اضافه کردن یک کنترلر (Controller)دیگر به نام MyAccountController

دستورات کد زیر را در صفحه MyAccountController اضافه کنید :

using MvcAuthentication.Models;  
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Mvc;  
using System.Web.Security;  
  
namespace MvcAuthentication.Controllers {  
    public class MyAccountController: Controller {  
        public ActionResult Login() {  
            return View();  
        }  
  
        [HttpPost]  
        [ValidateAntiForgeryToken]  
        public ActionResult Login(Login l, string ReturnUrl = "") {  
  
  
            //Here I am going to use Membership provider to validate user  
            if (ModelState.IsValid) {  
                var isValidUser = Membership.ValidateUser(l.Username, l.Password);  
                if (isValidUser) {  
                    FormsAuthentication.SetAuthCookie(l.Username, l.RememberMe);  
                    if (Url.IsLocalUrl(ReturnUrl)) {  
                        return Redirect(ReturnUrl);  
                    } else {  
                        return RedirectToAction("Index", "Home");  
                    }  
                }  
            }  
  
  
            ModelState.Remove("Password");  
            return View();  
        }  
  
        [Authorize]  
        public ActionResult Logout() {  
            FormsAuthentication.SignOut();  
            return RedirectToAction("Index", "Home");  
        }  
    }  
} 

مرحله هفتم : اضافه کردن view Myaccount که در دستور کد بالا در اکشن login باید یک view اضافه کنید و دستورات کد زیر را در صفحه Login.cshtml اضافه کنید.

@model MvcAuthentication.Models.Login  
  
@{  
    ViewBag.Title = "Login";  
}  
  
<h2>Login</h2>  
  
    @using (Html.BeginForm()) {  
        @Html.ValidationSummary(true)  
        @Html.AntiForgeryToken()  
            <fieldset>  
                <legend>Login</legend>  
                <div class="editor-label">  
                  @Html.LabelFor(model => model.Username)  
                </div>  
                <div class="editor-field">  
                    @Html.EditorFor(model => model.Username)  
                    @Html.ValidationMessageFor(model => model.Username)  
                </div>  
                <div class="editor-label">  
                   @Html.LabelFor(model => model.Password)  
             </div>  
             <div class="editor-field">  
                    @Html.EditorFor(model => model.Password)  
                    @Html.ValidationMessageFor(model => model.Password)  
             </div>  
             <div class="editor-label">  
                 @Html.LabelFor(model => model.RememberMe)  
             </div>  
                <div class="editor-field">  
                 @Html.EditorFor(model => model.RememberMe)  
                  @Html.ValidationMessageFor(model => model.RememberMe)  
             </div>  
             <p>  
                  <input type="submit" value="Create" />  
             </p>  
            </fieldset>     
  
    }  
  
  
    <div>  
         @Html.ActionLink("Back to List", "Index")  
    </div>  
  
    @section Scripts {  
        @Scripts.Render("~/bundles/jqueryval")  
    } 

مرحله هشتم : اضافه کردن Entity Data MOdel که در شکل زیر مشاهده می کنید.

مرحله نهم : اضافه کردن دو تا فایل CS.

دستورات کد زیر را در کلاسی که به نام صفحه MyRoleProvider.cs  و MyMembershipProvider.cs ایجاد کردید در آن اضافه کنید.

MyRoleProvider.cs

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Caching;  
using System.Web.Security;  
  
namespace MvcAuthentication {  
    public class MyRoleProvider: RoleProvider {  
        private int _cacheTimeoutInMinute = 20;  
        public override void AddUsersToRoles(string[] usernames, string[] roleNames) {  
            throw new NotImplementedException();  
        }  
  
        public override string ApplicationName {  
            get {  
                throw new NotImplementedException();  
            }  
            set {  
                throw new NotImplementedException();  
            }  
        }  
  
        public override void CreateRole(string roleName) {  
            throw new NotImplementedException();  
        }  
  
        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) {  
            throw new NotImplementedException();  
        }  
  
        public override string[] FindUsersInRole(string roleName, string usernameToMatch) {  
            throw new NotImplementedException();  
        }  
  
        public override string[] GetAllRoles() {  
            throw new NotImplementedException();  
        }  
  
        public override string[] GetRolesForUser(string username) {  
            if (!HttpContext.Current.User.Identity.IsAuthenticated) {  
                return null;  
            }  
  
            //check cache  
            var cacheKey = string.Format("{0}_role", username);  
            if (HttpRuntime.Cache[cacheKey] != null) {  
                return (string[]) HttpRuntime.Cache[cacheKey];  
            }  
            string[] roles = new string[] {};  
            using(RBACEntities dc = new RBACEntities()) {  
                roles = (from a in dc.Roles  
                join b in dc.UserRoles on a.RoleID equals b.RoleID  
                join c in dc.Users on b.UserID equals c.UserID  
                where c.Username.Equals(username)  
                select a.ROleName).ToArray < string > ();  
                if (roles.Count() > 0) {  
                    HttpRuntime.Cache.Insert(cacheKey, roles, null, DateTime.Now.AddMinutes(_cacheTimeoutInMinute), Cache.NoSlidingExpiration);  
  
                }  
            }  
            return roles;  
        }  
  
        public override string[] GetUsersInRole(string roleName) {  
            throw new NotImplementedException();  
        }  
  
        public override bool IsUserInRole(string username, string roleName) {  
            var userRoles = GetRolesForUser(username);  
            return userRoles.Contains(roleName);  
        }  
  
        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) {  
            throw new NotImplementedException();  
        }  
  
        public override bool RoleExists(string roleName) {  
            throw new NotImplementedException();  
        }  
    }  
} 

MyMembershipProvider.cs

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Security;  
  
namespace MvcAuthentication {  
    public class MyMembershipProvider: MembershipProvider {  
        public override string ApplicationName {  
            get {  
                throw new NotImplementedException();  
            }  
            set {  
                throw new NotImplementedException();  
            }  
        }  
  
        public override bool ChangePassword(string username, string oldPassword, string newPassword) {  
            throw new NotImplementedException();  
        }  
  
        public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) {  
            throw new NotImplementedException();  
        }  
  
        public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) {  
            throw new NotImplementedException();  
        }  
  
        public override bool DeleteUser(string username, bool deleteAllRelatedData) {  
            throw new NotImplementedException();  
        }  
  
        public override bool EnablePasswordReset {  
            get {  
                throw new NotImplementedException();  
            }  
        }  
  
        public override bool EnablePasswordRetrieval {  
            get {  
                throw new NotImplementedException();  
            }  
        }  
  
        public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) {  
            throw new NotImplementedException();  
        }  
  
        public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) {  
            throw new NotImplementedException();  
        }  
  
        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) {  
            throw new NotImplementedException();  
        }  
  
        public override int GetNumberOfUsersOnline() {  
            throw new NotImplementedException();  
        }  
  
        public override string GetPassword(string username, string answer) {  
            throw new NotImplementedException();  
        }  
  
        public override MembershipUser GetUser(string username, bool userIsOnline) {  
            throw new NotImplementedException();  
        }  
  
        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) {  
            throw new NotImplementedException();  
        }  
  
        public override string GetUserNameByEmail(string email) {  
            throw new NotImplementedException();  
        }  
  
        public override int MaxInvalidPasswordAttempts {  
            get {  
                throw new NotImplementedException();  
            }  
        }  
  
        public override int MinRequiredNonAlphanumericCharacters {  
            get {  
                throw new NotImplementedException();  
            }  
        }  
  
        public override int MinRequiredPasswordLength {  
            get {  
                throw new NotImplementedException();  
            }  
        }  
  
        public override int PasswordAttemptWindow {  
            get {  
                throw new NotImplementedException();  
            }  
        }  
  
        public override MembershipPasswordFormat PasswordFormat {  
            get {  
                throw new NotImplementedException();  
            }  
        }  
  
        public override string PasswordStrengthRegularExpression {  
            get {  
                throw new NotImplementedException();  
            }  
        }  
  
        public override bool RequiresQuestionAndAnswer {  
            get {  
                throw new NotImplementedException();  
            }  
        }  
  
        public override bool RequiresUniqueEmail {  
            get {  
                throw new NotImplementedException();  
            }  
        }  
  
        public override string ResetPassword(string username, string answer) {  
            throw new NotImplementedException();  
        }  
  
        public override bool UnlockUser(string userName) {  
            throw new NotImplementedException();  
        }  
  
        public override void UpdateUser(MembershipUser user) {  
            throw new NotImplementedException();  
        }  
  
        // Here In this example we will use only ValidateUser method, we will see remaining later like create user,  
        //update user change password and more  
  
        public override bool ValidateUser(string username, string password) {  
            //Will write code for validate user from our own database  
            using(RBACEntities dc = new RBACEntities()) {  
                var user = dc.Users.Where(a = > a.Username.Equals(username) && a.Password.Equals(password)).FirstOrDefault();  
                if (user != null) {  
                    return true;  
                }  
            }  
            return false;  
        }  
    }  
} 

مرحله دهم : در فایل Web.Config همانند شکل زیر تغییر دهید.

 

نرگس محمدی

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

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

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