本文体验在MVC中使用ASP.NET Identity 2.0,体验与用户身份安全有关的功能:
→install-package Microsoft.AspNet.Identity.Samples -Version 2.0.0-beta2 -Pre
安装后,在App_Start,Controllers, Models, Views等处都添加了多个文件。在App_Start/IdentityConfig.cs中有6个类和一个枚举:
● ApplicationUserManager:继承于泛型基类UserManager<ApplicationUser>, ApplicationUser用来处理用户的身份。
● ApplicationRoleManager
● EmailService
● SmsService
● ApplicationDbInitializer
● SignInHelper
● SignInStatus 枚举
□ Two-Factor Authentication机制
在ASP.NET Identity 2.0中,使用了"Two-Factor Authentication机制"来保证用户密码的安全,当用户密码可能存在不安全隐患的时候,系统会以短信或邮件的方式向用户发送安全码。
在ApplicationUserManager中的Create方法包含了验证用户名和密码以及发送安全码的逻辑:
PhoneNumberTokenProvider和EmailTokenProvider都继承于EmailTokenProvider,这个基类负责向用户发送短信或email。发送的前提是需要注册EmailService和SmsService,如下:
□ Account Lockout锁住帐号
当用户输错密码超过规定的次数,帐号就会被锁住。
在ApplicationUserManager中的Create方法也包含了锁住帐号的逻辑:
→在EmailService中编写发送右键的逻辑:
public class EmailService : IIdentityMessageService { public Task SendAsync(IdentityMessage message) { // Plug in your email service here to send an email. //配置 var mailMessage = new System.Net.Mail.MailMessage("qdjjx9441@sina.com", message.Destination, message.Subject, message.Body) //发送 SmtpClient client = new SmtpClient(); client.SendAsync(mailMessage, null); return Task.FromResult(0); } }
→在Web.config中的<configuration>节点下配置接收邮件的文件夹
<system.net>
<mailSettings>
<smtp deliveryMethod="SpecifiedPickupDirectory">
<specifiedPickupDirectory pickupDirectoryLocation="F:mailDrop"/>
</smtp>
</mailSettings>
</system.net>
→在Web.config中的<connectionStrings>节点配置连接字符串,用来把用户信息保存到数据库
<add name="DefaultConnection" connectionString=".;Initial Catalog=MVC_Identity-1-14;user id=sa;password=woshiniba;Integrated Security=SSPI"
providerName="System.Data.SqlClient" />
→AccontController中接收[HttpPost]的Register方法包含了用户注册后发送确认邮件的逻辑
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> Register(RegisterViewModel model) { if (ModelState.IsValid) { var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; var result = await UserManager.CreateAsync(user, model.Password); if (result.Succeeded) { var 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 this link: <a href="" + callbackUrl + "">link</a>"); ViewBag.Link = callbackUrl; return View("DisplayEmail"); } AddErrors(result); } // If we got this far, something failed, redisplay form return View(model); }
→运行项目 测试注册、确认邮件、登录
点击右上方的Register链接:
填写注册信息,点击注册:
注意:在Web.config中配置的mailDrop文件夹,需要创建,否则报错!
找到mailDrop文件夹,使用Foxmail打开后缀为eml的文件,看到:
点击链接地址:
点击"Click here to Log in"并登录:
→运行项目 测试账户锁定
修改App_Start/IdentityConfig.cs中, ApplicationUserManager类的相关部分为:
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(1);
manager.MaxFailedAccessAttemptsBeforeLockout = 2;
在App_Start/IdentityConfig.cs中,SignInHelper类的PasswordSignIn修改如下:
public async Task<SignInStatus> PasswordSignIn(string userName, string password, bool isPersistent, bool shouldLockout) { var user = await UserManager.FindByNameAsync(userName); //为测试帐号锁住而添加 await UserManager.IsLockedOutAsync(user.Id); //如果用户被锁住,这里返true await UserManager.AccessFailedAsync(user.Id);//记录登录失败的次数,如果登录失败次数大于或等于设定的次数,在设置锁住时间内,用户账户被锁住 await UserManager.SetLockoutEnabledAsync(user.Id, true);//确认用户账户被锁住是否被启用 if (user == null) { return SignInStatus.Failure; } if (await UserManager.IsLockedOutAsync(user.Id)) { return SignInStatus.LockedOut; } if (await UserManager.CheckPasswordAsync(user, password)) { return await SignInOrTwoFactor(user, isPersistent); } if (shouldLockout) { // If lockout is requested, increment access failed count which might lock out the user await UserManager.AccessFailedAsync(user.Id); if (await UserManager.IsLockedOutAsync(user.Id)) { return SignInStatus.LockedOut; } } return SignInStatus.Failure; }
再次登录,试着输入2次错误密码,出现提示帐号被锁住的界面:
当然还有一些其它功能,比如密码重置等。
参考资料:
Developing Secure ASP.NET MVC Applications using ASP.NET Identity 2.0