ASP.NET Core - 登录和注销

在本章中,我们将讨论登录和注销功能.与登录相比,注销实现起来相当简单.让我们继续布局视图,因为我们想要构建一个包含一些链接的UI.这将允许登录用户注销并显示用户名.

<!DOCTYPE html>  
<html> 
   <head> 
      <meta name = "viewport" content = "width = device-width" /> 
       <title>@ViewBag.Title</title> 
   </head> 

   <body> 
      <div> 
         @DateTime.Now 
      </div> 
      
      <div> 
         @RenderBody() 
      </div> 

   </body> 
</html>

  • 对于匿名用户,我们将显示登录链接.

  • 构建此UI所需的所有信息都可以从Razor视图上下文中获得.

  • 首先,让我们在布局视图中添加命名空间 System.Security.Claims .

@using System.Security.Claims 
<!DOCTYPE html>  
<html> 
   
   <head> 
      <meta name = "viewport" content = "width = device-width" /> 
      <title>@ViewBag.Title</title> 
   </head> 

   <body>
      <div> 
         @if (User.IsSignedIn()) { 
            <div>@User.GetUserName()</div> 
            <form method = "post" asp-controller = "Account" aspcontroller = "Logout"> 
               <input type = "submit" value = "Logout"/> 
            </form> 
         } else {  
            <a asp-controller = "Account" asp-action = "Login">Login</a> 
            <a asp-controller = "Account" asp-action = "Register">Register</a> 
         } 
      </div> 
    
      <div> 
         @DateTime.Now 
      </div> 
    
      <div> 
         @RenderBody() 
      </div> 

   </body> 
</html>

  • 每个Razor视图中都有一个User属性,我们想要构建将显示登录用户名称的UI.这里也提供了扩展方法 IsSignedIn .

  • 我们可以调用此方法,如果它返回true,我们可以在这里放置一些标记以显示用户名,显示注销按钮.

  • 现在,如果用户已登录,我们可以使用帮助方法显示用户的用户名 GetUserName .

  • 我们必须在表单中构建一个注销按钮,该按钮将发布到Web服务器.必须这样做,因为它会创建某些令人讨厌的条件,如果你允许一个简单的GET REQUEST允许用户离开.

  • 我们将强制这是一个帖子,当用户提交这个表单时,我们需要做的只是点击Logout操作,我们将通过AccountController实现,并注销用户.

  • 如果用户未登录且我们有匿名用户,那么我们需要显示一个链接,该链接将转到AccountController,特别是Login操作,并且它可以显示文本Login.

  • 我们还需要为新用户添加一个链接,以便注册并直接进入"注册"页面.

现在让我们转到AccountController并首先执行注销操作,如下面的程序所示.

[HttpPost] 
public async Task<IActionResult> Logout() { 
   await _signManager.SignOutAsync(); 
   return RedirectToAction("Index", "Home"); 
}

  • 此操作仅响应HttpPost.这是一个异步操作.我们将不得不在Identity框架上调用另一个异步方法.

  • 我们可以返回IActionResult的任务,并将该操作命名为Logout.

  • 注销的所有工作都是等待 SignInManager的SignOutAsync 方法.

  • 用户上下文现在已更改;我们现在有一个匿名用户.该视图将被重定向到主页,我们将返回到员工列表.

现在让我们继续构建我们的登录功能.在这里,我们需要一对动作,一个响应HttpGet请求并显示我们可以用来登录的表单,另一个响应HttpPost请求.

To首先,我们需要一个新的ViewModel来提取登录数据,因为登录与注册非常不同.所以,让我们添加一个新类并将其命名为 LoginViewModel .

public class LoginViewModel { 
   public string Username { get; set; }  
   
   [DataType(DataType.Password)] 
   public string Password { get; set; }  
   
   [Display(Name ="Remember Me")] 
   public bool RememberMe { get; set; } 
   public string ReturnUrl { get; set; } 

}

  • 当用户登录时,他们会必须提供一些信息,如用户名,密码.

  • 第三条信息必须是登录UI.这些带有一个小复选框,上面写着 - "你想记住我吗?"这是我们想要会话cookie之间的选择,还是我们想要更永久的cookie.

  • 为了允许这个功能,我们添加了一个布尔属性 RememberMe 我们使用了显示注释.现在,当我们构建标签时,文本记住我会显示一个空格.

  • 我们实际想要的最后一条信息这个ViewModel的一部分是拥有一个存储ReturnUrl的属性.

现在让我们添加将响应的Login操作获取请求,如以下程序所示.

[HttpGet] 
public IActionResult Login(string returnUrl = "") { 
   var model = new LoginViewModel { ReturnUrl = returnUrl }; 
   return View(model); 
}

  • 我们将采取 returnUrl 作为查询字符串中的参数.

  • returnUrl 可能并不总是存在.让我们将一个空字符串作为默认值.

我们现在将通过在

登录注销添加新项目

在中间窗格中,选择MVC View Page并将其命名为Login.cshtml,然后单击Add按钮.让我们在Login.cshtml文件中添加以下代码.

@model LoginViewModel 
@{ 
   ViewBag.Title = "Login"; 
}  
<h2>Login</h2>  

<form method = "post" asp-controller = "Account" asp-action = "Login" 
   asp-route-returnurl = "@Model.ReturnUrl"> 
      <div asp-validation-summary = "ValidationSummary.ModelOnly"></div> 
      
      <div> 
         <label asp-for = "Username"></label> 
         <input asp-for = "Username" /> 
         <span asp-validation-for = "Username"></span> 
      </div> 
      
      <div> 
         <label asp-for = "Password"></label> 
         <input asp-for = "Password" />
         <span asp-validation-for = "Password"></span> 
      </div> 
    
      <div> 
         <label asp-for = "RememberMe"></label> 
         <input asp-for = "RememberMe" /> 
         <span asp-validation-for = "RememberMe"></span> 
      </div> 
   <input type = "submit" value = "Login" /> 
</form>

  • 在此登录视图中,我们已将页面标题设置为Login,然后我们有一个表格会发布到 AccountLogin 行动.

  • 我们需要使用标签助手, asp- route-returnurl ,以确保表单回发到的URL中有ReturnUrl.

  • 我们需要发送ReturnUrl回到服务器,这样如果用户成功登录,我们就可以将其发送到他们想要去的地方.

  • 你做的任何事情在asp-route-,id或returnurl之后添加,无论你在那里有什么,它都会进入某个地方的请求,无论是进入URL路径还是作为查询字符串参数.

  • 我们有 ValidationSummary 和用户名,密码和RememberMe的输入,然后我们有一个提交按钮.

` AccountController ,并实现Post动作.这个响应HttpPost的动作.这将是一个Async方法,因为我们需要调用Identity框架并返回一个任务或IActionResult.

[HttpPost] 
public async Task<IActionResult> Login(LoginViewModel model) { 
   if (ModelState.IsValid) { 
      var result = await _signManager.PasswordSignInAsync(model.Username,
         model.Password, model.RememberMe,false); 
      
      if (result.Succeeded) { 
         if (!string.IsNullOrEmpty(model.ReturnUrl) && Url.IsLocalUrl(model.ReturnUrl)) {
            return Redirect(model.ReturnUrl);
         } else { 
            return RedirectToAction("Index", "Home"); 
         } 
      } 
   } 
   ModelState.AddModelError("","Invalid login attempt"); 
   return View(model); 
}

  • 我们称之为登录,现在我们希望收到一个LoginViewModel.

  • 我们需要检查ModelState是否有效.如果它有效,则通过调用SignInManager上的API来登录用户.

  • PasswordSignInAsync 方法将返回结果如果结果成功,我们就知道用户已成功登录.

  • 我们还有一个返回URL.如果它是有效的本地网址,我们将被重定向到返回网址.

  • 如果用户刚刚登录且没有任何具体位置go,我们将用户重定向到HomeController的Index操作.

  • 我们可能处于用户提供无效密码或用户名无效的情况.我们还需要添加模型错误,提示是否存在无效登录尝试.这有助于用户知道出现了什么问题.

现在让我们保存所有内容并运行应用程序.

登录注册

我们现在有登录和注册链接.让我们点击登录链接.

登录注册链接

让我们通过指定用户名密码与我们在上一章中创建的用户一起登录,然后选中记住我复选框.

当您单击"登录"按钮时,浏览器将询问您是否要保存本地主机的密码.让我们点击是按钮.

Logout

现在,让我们点击退出按钮注销.

退出按钮

作为匿名用户,让我们去尝试编辑员工详细信息.

匿名用户

您现在可以看到我们已被重定向到登录视图.

让我们使用您的用户名登录密码并选中记住我复选框.

Check Remember Me

现在,单击Login按钮.

登录按钮

您现在可以看到我们被定向到我们要编辑的URL.这是因为我们正确处理了返回网址.