在 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);
}
參考資料
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。