asp.net Identity2 角色(Role)的使用,三用户管理,用户控制器和视图

修改用户控制器AccountController,增加角色管理器。

public class AccountController : Controller

{

public AccountController()

{

}

public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, ApplicationRoleManager roleManager )

{

UserManager = userManager;

SignInManager = signInManager;

RoleManager = roleManager;

}

private ApplicationUserManager _userManager;

public ApplicationUserManager UserManager

{

get

{

return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();

}

private set

{

_userManager = value;

}

}

private ApplicationRoleManager _roleManager;

public ApplicationRoleManager RoleManager

{

get

{

return _roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>();

}

set

{

_roleManager = value;

}

}

1、登录

控制器:

[AllowAnonymous] //允许匿名访问,asp.net MVc5 中,只要操作方法有[AllowAnonymous]的数据注解,不管控制器的授权限制,都可实现匿名访问此操作方法。

public ActionResult Login(string returnUrl)

{

ViewBag.ReturnUrl = returnUrl;

return View();

}

// POST: /Account/Login

[HttpPost]

[AllowAnonymous]

[ValidateAntiForgeryToken]

public async Task<ActionResult> Login(LoginViewModel model)

{

if (!ModelState.IsValid)

{

return View(model);

}

var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);

switch (result)

{

case SignInStatus.Success:

if (User.IsInRole("Expert") || User.IsInRole("Student")) //对于不同的角色登录成功后跳转不同的页面。

{

return RedirectToAction("Index", "Home", new { area = "" });

}

else

{

return RedirectToAction("Index", "Home", new { area = "Admin" });

}

case SignInStatus.LockedOut:

return View("Lockout");

case SignInStatus.Failure:

default:

ModelState.AddModelError("", "用户名或者密码不正确。");

return View(model);

}

}

用户列表,显示所有用户,以及每个用户所拥有的角色名。

模型:

public class EditUserViewModel

{

[Display(Name = "用户ID")]

public string Id { get; set; }

[Required(AllowEmptyStrings=false)]

[Display(Name = "用户名")]

[StringLength(20, ErrorMessage = "{0}至少包含{2}个字符", MinimumLength = 6)]

public string UserName { get; set; }

[Required]

[EmailAddress]

[DataType(DataType.EmailAddress)]

[Display(Name = "电子邮件")]

public string Email { get; set; }

[Required]

[StringLength(20, ErrorMessage = "{0}少于{2}个字符", MinimumLength = 2)]

[Display(Name = "姓名")]

public string RealName { get; set; }

[Display(Name = "性别")]

[Required]

public Gender Gender { get; set; }

[DataType(DataType.Date)]

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

[Display(Name = "出生日期")]

public DateTime Birthday { get; set; }

public IEnumerable<System.Web.Mvc.SelectListItem> RolesList { get; set; } //使用SelectListItem 的泛型 集合,虽然在用户列表中不需要显示选中的角色,但这里也可以使用SelectListItem 泛型集合。

}

控制器:

//GET:/Account/Index

[Authorize(Roles = "SuperAdmin,Teacher")]

public async Task<ActionResult> Index()

{

var usersViewModel = new List<EditUserViewModel>();

foreach (var user in await UserManager.Users.OrderBy(u =>u.UserName).ToListAsync())

{

var userRoles =await UserManager.GetRolesAsync(user.Id);

var _userViewModel = new EditUserViewModel

{

Id = user.Id,

UserName = user.UserName,

Email = user.Email,

RealName = user.RealName,

Gender = user.Gender,

Birthday = user.Birthday,

RolesList = RoleManager.Roles.Where(x => userRoles.Contains(x.Name)) //满足所有角色中 此用户包含的角色,并建立投影 选择该角色的ID,和角色的名字。

.Select(x => new SelectListItem

{

Text = x.Name,

Value = x.Id

})

};

usersViewModel.Add(_userViewModel);

}

视图:

@model IEnumerable<MajorConstruction.Areas.Admin.Models.EditUserViewModel>

@{

ViewBag.Title = "用户列表";

}

@using Microsoft.AspNet.Identity

<h2>@ViewBag.Title</h2>

@if (User.IsInRole("SuperAdmin"))

{

<p>

@Html.ActionLink("新建用户", "Register", null, new { @class = "btn btn-primary" })

</p>

}

<hr />

<table class="table table-hover table-striped">

<thead>

<tr>

<th>

@Html.DisplayName("用户名")

</th>

<th>

@Html.DisplayNameFor(model => model.RealName)

</th>

<th>

@Html.DisplayNameFor(model => model.Gender)

</th>

<th>

@Html.DisplayNameFor(model => model.Birthday)

</th>

<th>

@Html.DisplayNameFor(model => model.Email)

</th>

<th>

该用户拥有的角色

</th>

<th></th>

</tr>

</thead>

<tbody>

@foreach (var item in Model)

{

<tr>

<td>

@Html.DisplayFor(modelItem => item.UserName)

</td>

<td>

@Html.DisplayFor(modelItem => item.RealName)

</td>

<td>

@Html.DisplayFor(modelItem => item.Gender)

</td>

<td>

@Html.DisplayFor(modelItem => item.Birthday)

</td>

<td>

@Html.DisplayFor(modelItem => item.Email)

</td>

<td>

@if (item.RolesList != null)

{

foreach (var roleItem in item.RolesList) //只需要列出

{

<text> @roleItem.Text |</text>

}

}

</td>

<td>

@if (User.IsInRole("SuperAdmin") && item.UserName != "administrator" && item.UserName != User.Identity.GetUserName())

{

@Html.ActionLink("修改信息", "EditUser", new { id = item.Id }, new { @class="btn btn-primary btn-xs",role="button"})

<text> </text>

@Html.ActionLink("重置密码", "ChangeUserPassword", new { id = item.Id }, new { @class = "btn btn-primary btn-xs", role = "button" })

<text> </text>

@Html.ActionLink("删除", "Delete", new { id = item.Id }, new { @class = "btn btn-primary btn-xs", role = "button" })

}

</td>

</tr>

}

</tbody>

</table>

创建用户并分配角色

控制器:

// GET: Admin/Account/Register //添加用户,只有管理员角色能够添加用户。

[Authorize(Roles = "SuperAdmin")]

public async Task<ActionResult> Register()

{

ViewBag.RoleID = new SelectList(await RoleManager.Roles.ToListAsync(), "Name", "Description");

return View();

}

//

// POST: /Account/Register

[Authorize(Roles = "SuperAdmin")]

[HttpPost]

[ValidateAntiForgeryToken]

public async Task<ActionResult> Register(RegisterViewModel model,params string[] selectedRoles) //可变数组参数。 模型绑定自动完成,给selectedRoles 可变参数数组传入参数。

{

if (ModelState.IsValid)

{

var user = new ApplicationUser { UserName = model.UserName, Email = model.Email, RealName = model.RealName, Gender = model.Gender, Birthday = model.Birthday, };

var userresult = await UserManager.CreateAsync(user, model.Password); //在数据库中创建了这个用户,那么就生成了UserID 了。

//给用户添加角色

if (userresult.Succeeded)

if (selectedRoles != null)

{

var result = await UserManager.AddToRolesAsync(user.Id, selectedRoles);

if (!result.Succeeded)

{

ModelState.AddModelError("", result.Errors.First());

ViewBag.RoleID = new SelectList(await RoleManager.Roles.ToListAsync(), "Name", "Description");

return View(model);

}

}

}

else

{

ModelState.AddModelError("", userresult.Errors.First());

ViewBag.RoleID = new SelectList(await RoleManager.Roles.ToListAsync(), "Name", "Description");

return View(model);

}

return RedirectToAction("Index"); //此处用得好。如果用户创建成功,但没有角色参数,则返回index.2、如果用户创建成功,角色添加成功,也返回index;

}

// 如果我们进行到这一步时某个地方出错,则重新显示表单

ViewBag.RoleID = new SelectList(await RoleManager.Roles.ToListAsync(), "Name", "Description");

return View(model);

}

视图:

@model MajorConstruction.Areas.Admin.Models.RegisterViewModel

@{

ViewBag.Title = "创建新账户";

}

<h2>@ViewBag.Title。</h2>

@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))

{

@Html.AntiForgeryToken()

<hr />

@Html.ValidationSummary("", new { @class = "text-danger" })

<div class="form-group">

@Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })

<div class="col-md-10">

@Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })

</div>

</div>

<div class="form-group">

@Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })

<div class="col-md-10">

@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })

</div>

</div>

<div class="form-group">

<label class="col-md-2 control-label">

选择用户角色

</label>

<div class="col-md-10">

@foreach (var item in (SelectList)ViewBag.RoleID) //遍历get方法返回的角色名称和角色描述。

{

<div class="checkbox">

<label>

<input type="checkbox" name="selectedRoles" value="@item.Value" />

@item.Text

</label>

</div>

}

</div>

</div>

<div class="form-group">

<div class="col-md-offset-2 col-md-10">

<input type="submit" class="btn btn-default" value="新建" />

</div>

</div>

}

@section Scripts {

@Scripts.Render("~/bundles/jqueryval")

}

管理员修改其它用户的信息

控制器:

//GET Account/EditUser 系统管理员修改其他人的信息

[Authorize(Roles = "SuperAdmin")]

public async Task<ActionResult> EditUser(string Id)

{

if(string.IsNullOrEmpty(Id))

{

return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

}

var _user = await UserManager.FindByIdAsync(Id);

if (_user == null)

{

return HttpNotFound();

}

var userRoles = await UserManager.GetRolesAsync(_user.Id);

var editUser = new EditUserViewModel

{

Id = _user.Id,

UserName = _user.UserName,

Email = _user.Email,

RealName = _user.RealName,

Gender = _user.Gender,

Birthday = _user.Birthday,

RolesList = RoleManager.Roles.ToList().Select(x => new SelectListItem() //建立一个投影,如果角色中包含当前用户的角色,就选中此角色。

{

Selected =userRoles.Contains(x.Name),

Text =x.Description,

Value =x.Name

})

};

return View(editUser);

}

//POST:// Admin/Account/EditUser/5 系统管理员修改其他人的信息

[Authorize(Roles = "SuperAdmin")]

[ValidateAntiForgeryToken]

[HttpPost]

public async Task<ActionResult> EditUser([Bind(Include = "Id,UserName,Email,RealName,Gender,Birthday")]EditUserViewModel user, params string[] selectedRole)

{

if (ModelState.IsValid)

{

var _user = await UserManager.FindByIdAsync(user.Id);

if (_user == null)

{

return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

}

_user.UserName=user.UserName;

_user.Email = user.Email;

_user.Email=user.Email;

_user.RealName = user.RealName;

_user.Gender=user.Gender;

_user.Birthday = user.Birthday;

var userRoles = await UserManager.GetRolesAsync(_user.Id);

selectedRole = selectedRole ?? new string[]{};

var result = await UserManager.AddToRolesAsync(user.Id, selectedRole.Except(userRoles).ToArray<string>()); //增加选中并且以前没有的角色组。然后转换成字符串数组。

if (!result.Succeeded)

{

ModelState.AddModelError("", result.Errors.First());

return View(user);

}

result = await UserManager.RemoveFromRolesAsync(user.Id, userRoles.Except(selectedRole).ToArray<string>()); //减少发前有的,但本次未选中的角色组

if (!result.Succeeded)

{

ModelState.AddModelError("", result.Errors.First());

return View(user);

}

UserManager.Update(_user); //这个语句是否有必要要呢?

return RedirectToAction("Index");

}

ModelState.AddModelError("", "绑定失败");

return View(user);

}

视图:

@model MajorConstruction.Areas.Admin.Models.EditUserViewModel

@{

ViewBag.Title = "EditUser";

}

<h2>修改用户信息</h2>

@using (Html.BeginForm())

{

@Html.AntiForgeryToken()

<div class="form-horizontal">

<hr />

@Html.ValidationSummary(true, "", new { @class = "text-danger" })

@Html.HiddenFor(model => model.Id)

<div class="form-group">

@Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-2" })

<div class="col-md-10">

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

@Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" })

</div>

</div>

<div class="form-group">

@Html.Label("编辑用户角色", new { @class ="control-label col-md-2" })

<div class="col-md-10">

@foreach (var item in Model.RolesList)

{

string checkedOrNot =item.Selected ? "checked": null; //判定该角色是否被选中。

<div class="checkbox">

<label>

<input type="checkbox" name="selectedRole" value="@item.Value" checked="@checkedOrNot">

@item.Text

</label>

</div>

}

</div>

</div>

<div class="form-group">

<div class="col-md-offset-2 col-md-10">

<input type="submit" value="修改" class="btn btn-default" />

</div>

</div>

</div>

}

@section Scripts {

@Scripts.Render("~/bundles/jqueryval")

}

系统管理员修改他人的密码:

控制器:

//GET://Account/ChangeUserPassword //系统管理员修改其他用户的密码

[Authorize(Roles = "SuperAdmin")]

public ActionResult ChangeUserPassword(string Id)

{

var user = UserManager.FindById(Id);

if (user == null)

return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

else

{

ResetPasswordViewModel _resetPasswordViewModel = new ResetPasswordViewModel()

{

UserName = user.UserName

};

return View(_resetPasswordViewModel);

}

}

//Post ://Account/ChangeUserPassword //系统管理员修改其他用户的密码

[Authorize(Roles = "SuperAdmin")]

[HttpPost]

[ValidateAntiForgeryToken]

public ActionResult ChangeUserPassword(ResetPasswordViewModel _resetPasswordViewModel)

{

if (!ModelState.IsValid)

{

return View(_resetPasswordViewModel);

}

var _user = UserManager.FindByName(_resetPasswordViewModel.UserName);

if (_user == null)

return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

var code =UserManager.GeneratePasswordResetToken(_user.Id); //给用户创建一个防伪造的密码 。

var result =UserManager.ResetPassword(_user.Id,code,_resetPasswordViewModel.Password); //重置密码。

if (result.Succeeded)

{

return RedirectToAction("Index");

}

return View();

}

视图:

@model MajorConstruction.Areas.Admin.Models.ResetPasswordViewModel

@{

ViewBag.Title = "更改用户密码";

}

<h2>@ViewBag.Title。</h2>

@using (Html.BeginForm())

{

@Html.AntiForgeryToken()

<div class="form-horizontal">

<hr />

@Html.ValidationSummary(true, "", new { @class = "text-danger" })

@*

@Html.HiddenFor(model =>model.UserName)

<div class="form-group">

@Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-2" })

<div class="col-md-10">

<p class="form-control-static">

@Html.DisplayFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } })

</p>

</div>

</div>*@ //将某个值返回POst方法,不可更改它的值,有几种方法,以上注释的为第一种:静态控件显示,隐藏字段传递值。 显示的是文本。

<div class="form-group">

@Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-2" })

<div class="col-md-10">

<input type="text" value="@Model.UserName" class="form-control" readonly="readonly" name="UserName" >,既可以传递表单值,又不更改表单里的数据。显示的是一个不可更改的表单值。

</div>

</div>

用户修改自己的个人信息

控制器:

//Get://Account/Edit 修改登录用户自己的信息

[Authorize(Roles = "SuperAdmin,Teacher")]

public ActionResult Edit()

{

var _user = UserManager.FindById(User.Identity.GetUserId());

if (_user == null)

return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

else

{

var editViewModelUser= new EditViewModel

{

RealName=_user.RealName,Gender=_user.Gender,Email=_user.Email,Birthday=_user.Birthday

};

return View(editViewModelUser);

}

}

//

//Post: Account/Edit 修改登录用户自己的信息

[Authorize(Roles = "SuperAdmin,Teacher")]

[ValidateAntiForgeryToken]

[HttpPost]

public ActionResult Edit(EditViewModel user)

{

var _user = UserManager.FindById(User.Identity.GetUserId());

if (_user == null)

return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

if (ModelState.IsValid)

{

_user.RealName = user.RealName;

_user.Gender = user.Gender;

_user.Birthday = user.Birthday;

_user.Email = user.Email;

UserManager.Update(_user);

return RedirectToAction("Index");

}

ModelState.AddModelError("","绑定失败");

return View(user);

}

视图:

@model MajorConstruction.Areas.Admin.Models.EditViewModel

@using Microsoft.AspNet.Identity;

@{

ViewBag.Title = "个人信息修改";

}

<h2>@ViewBag.Title。</h2>

@using (Html.BeginForm())

{

@Html.AntiForgeryToken()

<div class="form-horizontal">

<hr />

@Html.ValidationSummary(true,"", new { @class = "text-danger" })

<div class="form-group">

<label class="control-label col-md-2"> 用户名:</label>

<div class="col-md-10">

<p class="form-control-static">@User.Identity.GetUserName()</p> //静态控制显示get方法返回值。隐藏表单发送值。

</div>

</div>

<div class="form-group">

@Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })

<div class="col-md-10">

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

@Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })

</div>

</div>

登录用户更改自己的密码:

控制器:

//GET:// Admin/Account/ChangePassword //登录用户修改自己的密码

[Authorize(Roles = "SuperAdmin,Teacher")]

public ActionResult ChangePassword()

{

var user = UserManager.FindById(User.Identity.GetUserId());

if (user == null)

return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

else

{

var changePasswordViewModel = new ChangePasswordViewModel();

return View(changePasswordViewModel);

}

}

//POST:// Admin/Account/ChangePassword //登录用户修改自己的密码

[Authorize(Roles = "SuperAdmin,Teacher")]

[HttpPost]

[ValidateAntiForgeryToken]

public ActionResult ChangePassword(ChangePasswordViewModel userViewModel)

{

var userId = User.Identity.GetUserId();

var _user = UserManager.FindById(userId);

if (ModelState.IsValid)

{

if (UserManager.CheckPassword(_user, userViewModel.OldPassword)) //使用UserManager.CheckPassword(user,oldpassword) 检查密码是否正确。

{

UserManager.RemovePassword(userId); //修改密码的第二种方式:首先清空密码,再向该账户添加密码。

UserManager.AddPassword(userId, userViewModel.NewPassword);

return RedirectToAction("Index");

}

else

{

ModelState.AddModelError("", "输入的旧密码不正确");

return View(userViewModel);

}

}

else

{

ModelState.AddModelError("", "绑定失败");

return View(userViewModel);

}

}

视图:

@model MajorConstruction.Areas.Admin.Models.ChangePasswordViewModel

@using Microsoft.AspNet.Identity;

@{

ViewBag.Title = "个人密码修改";

}

<h2>@ViewBag.Title。</h2>

@using (Html.BeginForm())

{

@Html.AntiForgeryToken()

<div class="form-horizontal">

<hr />

@Html.ValidationSummary(true, "", new { @class = "text-danger" })

<div class="form-group">

@Html.Label("用户名", new { @class = "control-label col-md-2" })

<div class="col-md-10">

<p class="form-control-static"> @User.Identity.GetUserName()</p>

</div>

</div>

<div class="form-group">

@Html.LabelFor(model => model.OldPassword, htmlAttributes: new { @class = "control-label col-md-2" })

<div class="col-md-10">

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

@Html.ValidationMessageFor(model => model.OldPassword, "", new { @class = "text-danger" })

</div>

</div>