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" 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>

原文地址:https://www.cnblogs.com/liuyuanhao/p/4537356.html