1. 自定义属性
参考:ASP.NET Identity 2.0: Customizing Users and Roles
以扩展ApplicationUser为例。
1.1. 新增Password属性
修改IdentityModel.cs,ApplicationUser继承自IdentityUser,只需为它增加Password属性,用来保存密码明文。
public class ApplicationUser : IdentityUser { public ApplicationUser() : base() { } public ApplicationUser(string userName) : base(userName) { }
/// <summary> ///密码明文 /// </summary> [Required] [Display(Name = "密码")] public string Password { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager) { // 请注意,authenticationType 必须与 CookieAuthenticationOptions.AuthenticationType 中定义的相应项匹配 var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); // 在此处添加自定义用户声明 return userIdentity; } } |
1.2. 修改ViewModel
修改AccountViewModel.cs,采用用户名登录,为登录与注册ViewModel增加用户名。
public class LoginViewModel { [Required] [Display(Name = "用户名")] public string Username { get; set; }
[Required] [DataType(DataType.Password)] [Display(Name = "密码")] public string Password { get; set; }
[Display(Name = "记住我?")] public bool RememberMe { get; set; } } |
public class RegisterViewModel { [Required] [Display(Name = "用户名")] public string Username { get; set; }
[Required] [EmailAddress] [Display(Name = "电子邮件")] public string Email { get; set; }
[Required] [StringLength(100, ErrorMessage = "{0} 必须至少包含 {2} 个字符。", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "密码")] public string Password { get; set; }
[DataType(DataType.Password)] [Display(Name = "确认密码")] [Compare("Password", ErrorMessage = "密码和确认密码不匹配。")] public string ConfirmPassword { get; set; } } |
1.3. 修改Controller
修改AccountController.cs的Login与Register方法。
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) { if (!ModelState.IsValid) { return View(model); }
// 这不会计入到为执行帐户锁定而统计的登录失败次数中 // 若要在多次输入错误密码的情况下触发帐户锁定,请更改为 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("", "无效的登录尝试。"); return View(model); } } |
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> Register(RegisterViewModel model) { if (ModelState.IsValid) { var user = new ApplicationUser { UserName = model.Username, Password = model.Password, Email = model.Email }; var result = await UserManager.CreateAsync(user, model.Password); if (result.Succeeded) { await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
// 有关如何启用帐户确认和密码重置的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=320771 // 发送包含此链接的电子邮件 // 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, "确认你的帐户", "请通过单击 <a href="" + callbackUrl + "">這裏</a>来确认你的帐户");
return RedirectToAction("Index", "Home"); } AddErrors(result); }
// 如果我们进行到这一步时某个地方出错,则重新显示表单 return View(model); } |
1.4. 修改View
Login.cshtml
<h4>使用本地帐户登录。</h4> <hr /> @Html.ValidationSummary(true, "", 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" }) @Html.ValidationMessageFor(m => m.Username, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" }) <div class="col-md-10"> @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <div class="checkbox"> @Html.CheckBoxFor(m => m.RememberMe) @Html.LabelFor(m => m.RememberMe) </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> |
Register.cshtml
<h4>创建新帐户。</h4> <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"> @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" }) <div class="col-md-10"> @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) </div> </div> <div class="form-group"> @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" }) <div class="col-md-10"> @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" }) </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> |
1.5. 运行效果
登录
注册