在 ASP.NET Core MVC 上要做登入功能,或許會先想到 ASP.NET Core Identity,但它的複雜性實在太高,所以微軟在 ASP.NET Core MVC 上還提供另一種登入方式,就是單純以 Cookie 做認證。
在 Startup.cs 設定
首在開啟 Startup.cs,啟用 cookie 認證功能:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Home/Login"; }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseBrowserLink(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseAuthentication(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
在 ConfigureServices
函式中的 options.LoginPath = "/Home/Login";
這一行是設定登入頁面的網址,預設值是 /Account/Login
。接下來的 Configure
函式中的 app.UseAuthentication();
這一行,務必要在 app.UserMvc
前就呼叫。
Model 設計
接下來是 model 的設計,在 Models 資料夾中新增一個 UserModel.cs 檔案,並在裡面新增類別:
public class UserModel { public UserModel() { } public static UserModel Login(string account, string password) { UserModel user = null; if (account == "admin" && password == "yourpwd") { user = new UserModel(); user.Email = "admin@domain.com"; user.UserName = "admin"; user.UserId = "admin"; } return user; } public string Email { get; set; } public string UserName { get; set; } public string UserId { get; set; } }
UserModel 裡面除了一些使用者的個人資料,裡面還多了個 static 函式:Login,主要是用來做認證用,為了簡化所以我把帳密寫死在裡面,這部份的邏輯可以自己自由抽換。
另外,在登入時因為需要用到 controller 底的 HttpContext 屬性,所以索性就弄了個擴充方法:
public static class ControllerExtensionClass { public async static void SetUser(this Controller controller, UserModel user) { var claims = new List<Claim>(); claims.Add(new Claim("email", user.Email)); claims.Add(new Claim(nameof(user.UserId), user.UserId)); var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); await controller.HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), new AuthenticationProperties { IsPersistent = true }); } }
Controller 部份
而在 controller 部份,Login 部份的程式碼如下:
[HttpGet] public IActionResult Login() { return View(); } [HttpPost] public IActionResult Login(UserViewModel userModel) { string returnUrl = @"/Home/Permission"; UserModel user = UserModel.Login(userModel.Account, userModel.Password); if (user != null) { this.SetUser(user); return Redirect(returnUrl); } else { return View(); } }
Login 的部份利用了 UserViewModel 來當做參數,程式碼如下:
public class UserViewModel { public UserViewModel() { } public string Account { get; set; } public string Password { get; set; } }
會切開來的原因,在於我覺得 View 使用到的類別跟包含商業邏輯的 Model 分開,在其中一方做修改時才不會相互影響。
最後來看 View 部份,Login.cshtml:
@model CookieAuthenticationDemo.Models.ViewModels.UserViewModel @{ ViewData["Title"] = "Login"; } <h2>Login</h2> <h4>UserViewModel</h4> <hr /> <div class="row"> <div class="col-md-4"> <div class="text-danger"></div> <div class="form-group"> <span class="text-danger"></span> </div> <div class="form-group"> <span class="text-danger"></span> </div> <div class="form-group"> </div> </form> </div> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }
全部都完成後,controller 中需要認證的 action 只要掛上 Authorize
這個 attribute 就可以了,像是這樣:
[Authorize] public IActionResult Permission() { var claims = HttpContext.User.Claims; string content = string.Empty; foreach (var claim in claims) { content += claim.Value + " "; } return Content(content); }
參考資料
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。