修改用户控制器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" id="UserName" /> //第二种方法:使用原始的Html标记<input readonly ="readonly">,既可以传递表单值,又不更改表单里的数据。显示的是一个不可更改的表单值。
</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>