ASP.NET MVC Role manager Demo

Các bước dưới đây hướng dẫn cách tạo module để quản lý và phân quyền dựa trên vai trò người dùng (Role-based security)

  • Cấu hình web.config để chỉ đến cơ sở dữ liệu cần dùng

<add name=”DefaultConnection” connectionString=”Data Source=(local);Initial Catalog=DatTour;uid=sa;pwd=xxxxxx”
providerName=”System.Data.SqlClient” />

  • Tạo role và user admin mặc định

Mở file Startup.cs ngay trong thư mục gốc của ứng dụng, viết thêm đoạn mã sau

public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
createRolesandUsers();
}

// In this method we will create default User roles and Admin user for login
private void createRolesandUsers()
{
ApplicationDbContext context = new ApplicationDbContext();

var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
// In Startup iam creating first Admin Role and creating a default Admin User
if (!roleManager.RoleExists(“Admin”))
{

// first we create Admin rool
var role = new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();
role.Name = “Admin”;
roleManager.Create(role);

//Here we create a Admin super user who will maintain the website

var user = new ApplicationUser();
user.UserName = “khanhn”;
user.Email = “khanhdsp@gmail.com”;

string userPWD = “12121212”;

var chkUser = UserManager.Create(user, userPWD);

//Add default User to Role Admin
if (chkUser.Succeeded)
{
var result1 = UserManager.AddToRole(user.Id, “Admin”);

}
}

// creating Creating Manager role
if (!roleManager.RoleExists(“Manager”))
{
var role = new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();
role.Name = “Manager”;
roleManager.Create(role);

}

// creating Creating Employee role
if (!roleManager.RoleExists(“Employee”))
{
var role = new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();
role.Name = “Employee”;
roleManager.Create(role);

}
}
}

Bây giờ chạy ứng dụng có thể kiểm tra được role và user được tạo ra trong csdl

  • Customize form đăng ký (Register)

Bổ sung thêm 2 đoạn code highlight dưới đây vào view Register.cshtml

@model shanuMVCUserRoles.Models.RegisterViewModel   
@{   
    ViewBag.Title = "Register";   
}   
<h2>@ViewBag.Title.</h2>   
@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))   
{   
    @Html.AntiForgeryToken()   
    <h4>Create a new account.</h4>   
    <hr />   
    @Html.ValidationSummary("", new { @class = "text-danger" })   
    
 class="form-group"           @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })            
 class="col-md-10"               @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })            
        </div>        
 class="form-group"           @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })            
 class="col-md-10"               @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })            
        </div>        
 class="form-group"           @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })            
 class="col-md-10"               @Html.PasswordFor(m => m.Password, new { @class = "form-control" })            
        </div>        
 class="form-group"           @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })            
 class="col-md-10"               @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })            
        </div>        
 class="form-group"           @Html.Label("user Role", new { @class = "col-md-2 control-label" })            
 class="col-md-10"               @*@Html.DropDownList("Name")*@                @Html.DropDownList("UserRoles", (SelectList)ViewBag.Name, " ")            
        </div>        
 class="form-group"           
 class="col-md-offset-2 col-md-10"                type="submit" class="btn btn-default" value="Register" />            
        </div>    }    @section Scripts {        @Scripts.Render("~/bundles/jqueryval")    }
  • Thay đổi RegisterViewModel trong lớp AccountViewModel.cs
public class RegisterViewModel   
    {   
        [Required]   
        [Display(Name = "UserRoles")]   
        public string UserRoles { getset; }   
   
        [Required]   
        [EmailAddress]   
        [Display(Name = "Email")]   
        public string Email { getset; }   
   
        [Required]   
        [Display(Name = "UserName")]   
        public string UserName { getset; }   
   
        [Required]   
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]   
        [DataType(DataType.Password)]   
        [Display(Name = "Password")]   
        public string Password { getset; }   
   
        [DataType(DataType.Password)]   
        [Display(Name = "Confirm password")]   
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]   
        public string ConfirmPassword { getset; }   
    }
  • Thay đổi code sau trong AccountController.cs

ApplicationDbContext context;

public AccountController()
{
context = new ApplicationDbContext();
}

[AllowAnonymous]
public ActionResult Register()
{
ViewBag.Name = new SelectList(context.Roles.Where(u =>!u.Name.Contains(“Admin”)).ToList(), “Name”, “Name”);
return View();
}

  • Sửa lại mã trong Register method của AccountController.cs
// POST: /Account/Register   
        [HttpPost]   
        [AllowAnonymous]   
        [ValidateAntiForgeryToken]   
        public async Task<ActionResult> Register(RegisterViewModel model)   
        {   
            if (ModelState.IsValid)   
            {   
                var user = new ApplicationUser { UserName = model.UserName, Email = model.Email };   
                var result = await UserManager.CreateAsync(user, model.Password);   
                if (result.Succeeded)   
                {   
                    await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);   
   
                    // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771   
                    // Send an email with this link   
                    // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);   
                    // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);   
                    // await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");   
                    //Assign Role to user Here      
                    await this.UserManager.AddToRoleAsync(user.Id, model.UserRoles);   
                    //Ends Here    
                    return RedirectToAction("Index""Users");   
                }   
                ViewBag.Name = new SelectList(context.Roles.Where(u => !u.Name.Contains("Admin"))   
                                          .ToList(), "Name""Name");   
                AddErrors(result);   
            }   
   
            // If we got this far, something failed, redisplay form   
            return View(model);   
        }
  • Customize Login.cshtml để đăng nhập bằng UserName thay cho Email
@using shanuMVCUserRoles.Models   
@model LoginViewModel   
@{   
    ViewBag.Title = "Log in";   
}   
   
<h2>@ViewBag.Title</h2>   
class="row">        
class="col-md-8">            
"loginForm">                @using (Html.BeginForm("Login""Account"new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))                {                    @Html.AntiForgeryToken()                    

Use a local account to log in.

                    
                    @Html.ValidationSummary(true""new { @class = "text-danger" })                    
class="form-group">                        @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })                        
class="col-md-10">                            @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })                            @Html.ValidationMessageFor(m => m.UserName, ""new { @class = "text-danger" })                        
                    </div>                    
class="form-group">                        @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })                        
class="col-md-10">                            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })                            @Html.ValidationMessageFor(m => m.Password, ""new { @class = "text-danger" })                        
                    </div>                    
class="form-group">                        
class="col-md-offset-2 col-md-10">                            
class="checkbox">                                @Html.CheckBoxFor(m => m.RememberMe)                                @Html.LabelFor(m => m.RememberMe)                            
                        </div>                    </div>                    
class="form-group">                        
class="col-md-offset-2 col-md-10">                            "submit" value="Log in" class="btn btn-default" />                        
                    </div>                    <p>                        @Html.ActionLink("Register as a new user""Register")                    </p>                    @* Enable this once you have account confirmation enabled for password reset functionality                        <p>                            @Html.ActionLink("Forgot your password?""ForgotPassword")                        </p>*@    }            </section>        </div>        
class="col-md-4">            
"socialLoginForm">                @Html.Partial("_ExternalLoginsListPartial"new ExternalLoginListViewModel { ReturnUrl = ViewBag.ReturnUrl })            
        
    </div>        @section Scripts {        @Scripts.Render("~/bundles/jqueryval")    }
  • Sửa lại LoginViewModel
public class LoginViewModel   
    {   
        [Required]   
        [Display(Name = "UserName")]   
        public string UserName { getset; }   
 
        [Required]   
        [DataType(DataType.Password)]   
        [Display(Name = "Password")]   
        public string Password { getset; }   
   
        [Display(Name = "Remember me?")]   
        public bool RememberMe { getset; }   
    }
  • Sửa lại code của Login action method của AccountController.cs
// POST: /Account/Login   
        [HttpPost]   
        [AllowAnonymous]   
        [ValidateAntiForgeryToken]   
        public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)   
        {   
            if (!ModelState.IsValid)   
            {   
                return View(model);   
            }   
   
            // This doesn't count login failures towards account lockout   
            // To enable password failures to trigger account lockout, change to shouldLockout: true   
            var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);   
            switch (result)   
            {   
                case SignInStatus.Success:   
                    return RedirectToLocal(returnUrl);   
                case SignInStatus.LockedOut:   
                    return View("Lockout");   
                case SignInStatus.RequiresVerification:   
                    return RedirectToAction("SendCode"new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });   
                case SignInStatus.Failure:   
                default:   
                    ModelState.AddModelError("""Invalid login attempt.");   
                    return View(model);   
            }   
        }   
  • Tạo UsersController.cs và viết code cho Controller như sau

[Authorize]
public class UsersController : Controller
{
// GET: Users
public ActionResult Index()
{
if (User.Identity.IsAuthenticated)
{
var user = User.Identity;
ViewBag.Name = user.Name;

ViewBag.displayMenu = “No”;

if (isAdminUser())
{
ViewBag.displayMenu = “Yes”;
}
return View();
}
else
{
ViewBag.Name = “Not Logged IN”;
}
return View();
}
public Boolean isAdminUser()
{
if (User.Identity.IsAuthenticated)
{
var user = User.Identity;
ApplicationDbContext context = new ApplicationDbContext();
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var s = UserManager.GetRoles(user.GetUserId());
if (s[0].ToString() == “Admin”)
{
return true;
}
else
{
return false;
}
}
return false;
}
}

  • Index.cshtml view của Users controller

@{
ViewBag.Title = “Index”;
}

@if (ViewBag.displayMenu == “Yes”)
{
<h1>Welcome Admin. Now you can create user Role.</h1>
<h3>
<li>@Html.ActionLink(“Manage Role”, “Index”, “Role”)</li>
</h3>
}
else
{
<h2> Welcome <strong>@ViewBag.Name</strong> 🙂 .We will add user module soon </h2>
}

  • Tạo Empty RoleController.cs và viết code như sau

[Authorize]
public class RoleController : Controller
{
ApplicationDbContext context;

public RoleController()
{
context = new ApplicationDbContext();
}
// GET: Role
public ActionResult Index()
{
if (User.Identity.IsAuthenticated)
{
if (!isAdminUser())
{
return RedirectToAction(“Index”, “Home”);
}
}
else
{
return RedirectToAction(“Index”, “Home”);
}
var Roles = context.Roles.ToList();
return View(Roles);
}

public Boolean isAdminUser()
{
if (User.Identity.IsAuthenticated)
{
var user = User.Identity;
ApplicationDbContext context = new ApplicationDbContext();
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var s = UserManager.GetRoles(user.GetUserId());
if (s[0].ToString() == “Admin”)
{
return true;
}
else
{
return false;
}
}
return false;
}
/// <summary>
/// Create a New role
/// </summary>
/// <returns></returns>
public ActionResult Create()
{
if (User.Identity.IsAuthenticated)
{
if (!isAdminUser())
{
return RedirectToAction(“Index”, “Home”);
}
}
else
{
return RedirectToAction(“Index”, “Home”);
}
var Role = new IdentityRole();
return View(Role);
}

/// <summary>
/// Create a New Role
/// </summary>
/// <param name=”Role”></param>
/// <returns></returns>
[HttpPost]
public ActionResult Create(IdentityRole Role)
{
if (User.Identity.IsAuthenticated)
{
if (!isAdminUser())
{
return RedirectToAction(“Index”, “Home”);
}
}
else
{
return RedirectToAction(“Index”, “Home”);
}
context.Roles.Add(Role);
context.SaveChanges();
return RedirectToAction(“Index”);
}
}

  • Tạo Index view và create view cho RoleController như sau

Index.cshtml

@model IEnumerable<Microsoft.AspNet.Identity.EntityFramework.IdentityRole>
@{
ViewBag.Title = “Add Role”;
}
<table style=” background-color:#FFFFFF; border: dashed 3px #6D7B8D; padding: 5px;width: 99%;table-layout:fixed;” cellpadding=”6″ cellspacing=”6″>
<tr style=”height: 30px; background-color:#336699 ; color:#FFFFFF ;border: solid 1px #659EC7;”>
<td align=”center” colspan=”2″>
<h2> Create User Roles</h2>
</td>

</tr>

<tr>
<td>
<table id=”tbrole” style=”width:100%; border:dotted 1px; background-color:gainsboro; padding-left:10px;”>

@foreach (var item in Model)
{
<tr>
<td style=”width:100%; border:dotted 1px;”>
@item.Name
</td>
</tr>}
</table>
</td>
<td align=”right” style=”color:#FFFFFF;padding-right:10;”>
<h3> @Html.ActionLink(“Click to Create New Role”, “Create”, “Role”) </h3>
</td>
</tr>
</table>

Create.cshtml

@model Microsoft.AspNet.Identity.EntityFramework.IdentityRole
@{
ViewBag.Title = “Add New Role”;
}
<h2>Add New User Role:</h2>

@using (Html.BeginForm())
{
<p> Enter User Role Name:</p>

@Html.EditorFor(m => m.Name)
<input type=”submit” value=”Create Role” />
}

Code hơi dài, hy vọng bạn thực hiện theo các bước thành công. Nếu không bạn có thể download mã nguồn ở link này

Source: bài viết có tham khảo demo của Micrsoft.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s