构建认证:
1:创建用户模型
最简单的用户模型,只包含用户名和密码
该用户模型可以和Entityframework 进行绑定,实现与数据库的联动
位于命名空间 MVC_BASE.Controllers 之下 (仅举例,根据自己项目实际放置)
public class LoginViewModel
{
public string Username { get; set; }
public string Password { get; set; }
}
2:创建控制器
登录页面,一个空参数,用HttpGet ,保证登录页面可加载。
另一个传入 LoginViewModel 参数,用HttpPost 接收前端From传进来的登录信息。
[HttpGet]
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel model)
//public IActionResult Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
// 验证用户名和密码的逻辑
if (model.Username!="")//(/*用户名和密码正确*/)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, model.Username),
new Claim("Passwork",model.Password),
new Claim(ClaimTypes.Role,"Admin5"),
// 添加其他需要的Claims
};
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
return RedirectToAction("Index", "Home");
}
}
ModelState.AddModelError("", "用户名或密码错误");
return View(model);
}
另外,再创建一个控制器,用于取消登录。
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction("Index", "Home");
}
3:创建前端代码
登录页面通过 TagHelper 构建,用@model 强类型的方式引入 LoginViewModel 。
完整代码如下:
@{
ViewData["Title"] = "Login";
}
@model MVC_BASE.Controllers.LoginViewModel;
<h1>Login</h1>
<form asp-action="Login" asp-controller="Home" method="post">
<div>
<label asp-for="Username"></label>
<input asp-for="Username" />
</div>
<div>
<label asp-for="Password"></label>
<input asp-for="Password" />
</div>
<button type="submit">登录</button>
</form>
我前端页面采用了_Layout 布局,在布局的右上角有一个登录按钮,
未登录时,显示“Login”,点击后进入登录页面
登录后,显示“Logout”,点击后退出登录,并重定位到Index页面(控制器中体现)
_Layout.cshtml中代码添加
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
@if (User.Identity!=null && User.Identity.IsAuthenticated)
{
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Logout">Logout</a>
}
else
{
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Login">Login</a>
}
</li>
</ul>
代码中,User.Identity.IsAuthenticated 作用就是判断是否登录认证过。
4:【重点】启动注入
要实现认证和授权,需要完善启动注入项。
在 programs.cs中添加Services 信息注入
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Home/Login"; //未登录时,重定位到该页面
options.AccessDeniedPath = "/Home/Error"; //已登录,但没有权限时,定位到该页面
options.Cookie.Name = "YourCookieName";
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Strict;
//options.Cookie.ExpireTimeSpan = TimeSpan.FromDays(1);
});
builder.Services.AddAuthorization();
builder.Services.AddControllersWithViews();
var app = builder.Build();
WebApplication中注入功能
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication(); //认证
app.UseRouting();
app.UseAuthorization(); //授权
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
--以上,即完成了认证
实现授权
在认证相关的控制器代码
[HttpPost]
publicasyncTask<IActionResult>Login(LoginViewModel model)
中有一段
new Claim(ClaimTypes.Role,"Admin5"),
即添加了一个角色 Admin5
如果相关页面需要符合该角色的用户登录后才能访问,那么相关控制器可以添加属性如下:
[Authorize(Roles = "Admin5")]
public IActionResult Privacy()
{
return View();
}
具体的属性用法可以参考微软官方文档
如果仅仅是登录后才可视,不分角色权限的话,控制器权限属性可以简单为
[Authorize]
public IActionResult Privacy()
{
return View();
}
-- 以上,即完成了授权