My last preparatory step is to create the view that will be rendered to gather credentials from the user. Listing 14-4 shows the contents of the Views/Account/Login.cshtml file, which I created by right-clicking the Index action method and selecting Add View from the pop-up menu.
最后一项准备步骤是创建一个视图,用以收集来自于用户的凭据。清单14-4显示了Views/Account/Login.cshtml文件的内容,这是通过右击Index动作方法,然后从弹出菜单选择“Add View(添加视图)”而创建的。
Listing 14-4. The Contents of the Login.cshtml File
清单14-4. Login.cshtml文件的内容
@Html.ValidationSummary()
@using (Html.BeginForm()) { @Html.AntiForgeryToken(); <input type="hidden" value="@ViewBag.returnUrl" /> <div> <label>Name</label> @Html.TextBoxFor(x => x.Name, new { @class = "form-control" }) </div> <div> <label>Password</label> @Html.PasswordFor(x => x.Password, new { @class = "form-control" }) </div> <button type="submit">Log In</button> }
The only notable aspects of this view are using the Html.AntiForgeryToken helper and creating a hidden input element to preserve the returnUrl argument. In all other respects, this is a standard Razor view, but it completes the preparations for authentication and demonstrates the way that unauthenticated requests are intercepted and redirected. To test the new controller, start the application and request the /Home/Index URL. You will be redirected to the /Account/Login URL, as shown in Figure 14-2.
该视图唯一要注意的方面是使用了Html.AntiForgeryToken辅助器,并创建了一个隐藏的input元素,以保护returnUrl参数。在其他方面,这是一个标准的Razor视图,但它实现了认证的准备工作,并能演示被拦截且被重定向的未认证请求的情况。为了测试这个新的控制器,启动应用程序,并请求/Home/Index。你将被重定向到/Account/Login,如图14-2所示。
Figure 14-2. Prompting the user for authentication credentials
图14-2. 提示用户输入认证凭据
14.2.3 添加用户认证
Requests for protected URLs are being correctly redirected to the Account controller, but the credentials provided by the user are not yet used for authentication. In Listing 14-5, you can see how I have completed the implementation of the Login action.
发送给受保护URL的请求会被正确地重定向到Account控制器,但由用户提供的凭据尚未被用于认证。从清单14-5可以看出如何完成Login动作的实现。
Listing 14-5. Adding Authentication to the AccountController.cs File
清单14-5. 在AccountController.cs文件中添加认证
namespace Users.Controllers {
[Authorize] public class AccountController : Controller {
[AllowAnonymous] public ActionResult Login(string returnUrl) { ViewBag.returnUrl = returnUrl; return View(); }
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> Login(LoginModel details, string returnUrl) { if (ModelState.IsValid) { AppUser user = await UserManager.FindAsync(details.Name, details.Password); if (user == null) { ModelState.AddModelError("", "Invalid name or password."); } else { ClaimsIdentity ident = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie); AuthManager.SignOut(); AuthManager.SignIn(new AuthenticationProperties { IsPersistent = false}, ident); return Redirect(returnUrl); } } ViewBag.returnUrl = returnUrl; return View(details); }
private IAuthenticationManager AuthManager { get { return HttpContext.GetOwinContext().Authentication; } } private AppUserManager UserManager { get { return HttpContext.GetOwinContext().GetUserManager<AppUserManager>(); } } } }
The simplest part is checking the credentials, which I do through the FindAsync method of the AppUserManager class, which you will remember as the user manager class from Chapter 13:
最简单的部分是检查凭据,这是通过AppUserManager类的FindAsync方法来做的,你可能还记得,AppUserManager是第13章的用户管理器类。
... AppUser user = await UserManager.FindAsync(details.Name, details.Password); ...