在 .NET Core 3.0 中使用内存数据库进行基于身份的身份验证






4.53/5 (4投票s)
本文演示了如何在 .NET Core 3.0 中使用内存数据库添加基于身份的身份验证。
引言
身份验证是根据个人的身份确定或授予其访问系统或用户权限的过程。在 .NET Core 中,有多种进行身份验证的选项。本文演示了如何在 .NET Core 3.0 中使用内存数据库添加基于身份的身份验证。
背景
在上一篇文章中,我解释了 基于 Cookie 的 .NET Core 3.0 身份验证。
必备组件
创建 Web 应用程序的步骤
- 转到 **Visual Studio 2019**,然后从选项列表中选择 **创建新项目**。
- 选择该选项后,将打开一个新窗口以选择项目模板。
- 选择“**ASP.NET Core Web 应用程序**”并单击 **下一步** 按钮。
- 将打开一个新屏幕来配置新项目。根据您的需求提供 **项目名称**、**位置**、**解决方案名称**。按 **创建** 按钮。
- 单击 **创建** 按钮后,将打开一个新屏幕来配置项目相关信息,例如您想为 Web 应用程序创建哪个环境? **.NET Framework 或 .NET Core。** 从下拉列表中选择 **.NET Core** 和 **ASP.NET Core** 版本。然后,从列表中选择 **Web 应用程序(模型-视图-控制器)** 选项,然后按 **创建** 按钮来创建项目。
- 现在我们的项目将以 .NET Core 环境的基本结构打开。您可以在解决方案资源管理器中观察到,它将包含 *Controllers*、*Models* ** 和 *Views*** 文件夹,以及“*Startup.cs*”和其他文件,如下图所示:
- 运行您的应用程序,检查创建的 Web 应用程序是否正常运行。默认情况下,它将打开项目的“主页”(Home 控制器的 Index 页)。
安装以下版本为 3.0.0 或更高版本的 NuGet 包
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.InMemory
Microsoft.EntityFrameworkCore.Identity.EntityFrameworkCore
集成身份验证
IdentityDbContext
:提供管理身份表所需的所有DbSet
属性。ApplicationDbContext
:用户定义的DbContext
类继承自IdentityDbContext
来管理用户身份。UseInMemoryDatabase
:将用户信息存储在内存中以用于身份验证,而不是使用任何数据库。AppUser
:用户定义的类,继承自IdentityUser
以添加用户的额外属性。UserManager
:用于管理用户信息,例如创建用户信息、删除用户信息。SignInManager
:处理与HttpContext
的通信以及用户登录/注销功能。[Authorize]
:此属性有助于验证用户以访问控制器(用户信息)。
步骤 1
创建一个名为 *Data* 的新文件夹,并将 ApplicationDbContext
** 添加到其中,然后将以下代码行放入其中:
using DemoIdentityAuthentication.Models;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace DemoIdentityAuthentication.Data
{
// IdentityDbContext contains all the user tables
public class ApplicationDbContext : IdentityDbContext<AppUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
}
第二步
在 *Models* 文件夹中添加一个名为 AppUser
** 的新类,并将以下代码行放入其中:
using Microsoft.AspNetCore.Identity;
namespace DemoIdentityAuthentication.Models
{
public class AppUser : IdentityUser
{
public string Name { get; set; }
public string DateOfBirth { get; set; }
public string Password { get; set; }
}
}
步骤 3
对 *Startup.cs* 文件的更改
using DemoIdentityAuthentication.Data;
using DemoIdentityAuthentication.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
namespace DemoIdentityAuthentication
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(config =>
{
// for in memory database
config.UseInMemoryDatabase("MemoryBaseDataBase");
});
// AddIdentity :- Registers the services
services.AddIdentity<AppUser, IdentityRole>(config =>
{
// User defined password policy settings.
config.Password.RequiredLength = 4;
config.Password.RequireDigit = false;
config.Password.RequireNonAlphanumeric = false;
config.Password.RequireUppercase = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Cookie settings
services.ConfigureApplicationCookie(config =>
{
config.Cookie.Name = "DemoProjectCookie";
config.LoginPath = "/Home/Login"; // User defined login path
config.ExpireTimeSpan = TimeSpan.FromMinutes(5);
});
services.AddControllersWithViews();
}
// This method gets called by the runtime.
// Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days.
// You may want to change this for production scenarios,
// see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
步骤 4
使用新的 Action 方法更新 HomeController
**
- **Login**:用于用户登录。
- **Register**:用于注册新用户。
- **Logout**:用于注销当前用户。
- **UserInfo with Authorize tag**:用于显示有效用户的用户信息,并限制无效用户访问。
将以下代码行放入 HomeController
:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using DemoIdentityAuthentication.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Authorization;
namespace DemoIdentityAuthentication.Controllers
{
public class HomeController : Controller
{
private readonly UserManager<AppUser> _userManager;
private readonly SignInManager<AppUser> _signInManager;
public HomeController(
UserManager<AppUser> userManager,
SignInManager<AppUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
public IActionResult Index()
{
return View();
}
[Authorize]
public async Task<IActionResult> UserInfo()
{
var user =
await _userManager.GetUserAsync(HttpContext.User).ConfigureAwait(false);
if (user == null)
{
RedirectToAction("Login");
}
//login functionality
return View(user);
}
[HttpGet]
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(AppUser appUser)
{
//login functionality
var user = await _userManager.FindByNameAsync(appUser.UserName);
if (user != null)
{
//sign in
var signInResult = await _signInManager.PasswordSignInAsync
(user, appUser.Password, false, false);
if (signInResult.Succeeded)
{
return RedirectToAction("Index");
}
}
return RedirectToAction("Register");
}
public IActionResult Register()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Register(AppUser appUser)
{
//register functionality
var user = new AppUser
{
Id = "101",
UserName = appUser.UserName,
Email = appUser.Email,
Name = appUser.Name,
DateOfBirth = appUser.DateOfBirth,
Password = appUser.Password
};
var result = await _userManager.CreateAsync(user, user.Password);
if (result.Succeeded)
{
// User sign
// sign in
var signInResult = await _signInManager.PasswordSignInAsync
(user, user.Password, false, false);
if (signInResult.Succeeded)
{
return RedirectToAction("Index");
}
}
return View();
}
public async Task<IActionResult> LogOut(string username, string password)
{
await _signInManager.SignOutAsync();
return RedirectToAction("Index");
}
}
}
步骤 5
为 HomeController
** 添加视图**
- 转到 *Views* 文件夹并选择 *Home* 文件夹。
- 右键单击 *Home* 文件夹以选择添加选项,然后选择视图。
- 将弹出一个窗口以添加视图。
- 将 **视图名称** 提供为
Login
,将 **模板** 选择为Empty
,选择 **使用布局页**,然后按 **添加** 按钮。将在 *Home* 文件夹中创建一个新的 *Login.cshtml* 文件。请参考下图添加视图: - 对其他视图也遵循相同的步骤,并为
UserInfo
** 操作和Register
** 操作创建视图。 - Login.cshtml ** 页面的代码**
@model DemoIdentityAuthentication.Models.AppUser <h1>User Login</h1> <form asp-controller="Home" asp-action="Login"> <div class="form-group col-sm-6"> <label for="Username">Username</label> <input type="text" class="form-control" id="Username" asp-for="UserName" placeholder="Enter username"> </div> <div class="form-group col-sm-6"> <label for="Password">Password</label> <input type="password" class="form-control" id="Password" asp-for="Password" placeholder="Enter password"> </div> <div class="form-group col-sm-6"> <button type="submit" class="btn btn-primary">Login</button> </div> </form>
@model DemoIdentityAuthentication.Models.AppUser @{ ViewData["Title"] = "Register"; } <h1>User Register</h1> <form method="post" asp-controller="Home" asp-action="Register"> <div class="form-group col-sm-6"> <label for="Name">Name</label> <input type="text" class="form-control" id="Name" asp-for="Name" placeholder="Enter name"> </div> <div class="form-group col-sm-6"> <label for="EmailId">Email Id</label> <input type="email" class="form-control" id="EmailId" asp-for="Email" placeholder="Enter email id"> </div> <div class="form-group col-sm-6"> <label for="Username">Username</label> <input type="text" class="form-control" id="Username" asp-for="UserName" placeholder="Enter username"> </div> <div class="form-group col-sm-6"> <label for="Password">Password</label> <input type="password" class="form-control" id="Password" asp-for="Password" placeholder="Enter password"> </div> <div class="form-group col-sm-6"> <label for="DOB">Date Of Birth</label> <input type="text" class="form-control" id="DOB" asp-for="DateOfBirth" placeholder="Enter date of birth"> </div> <div class="form-group col-sm-6"> <button type="submit" class="btn btn-primary">Register</button> </div> </form>
- UserInfo.cshtml 页面的代码
@model DemoIdentityAuthentication.Models.AppUser <h1>User Information</h1> <table> <tr> <td>Name:- </td> <td>@Html.DisplayFor(model => model.Name)</td> </tr> <tr> <td>Email:- </td> <td>@Html.DisplayFor(model => model.Email)</td> </tr> <tr> <td>Username:- </td> <td>@Html.DisplayFor(model => model.UserName)</td> </tr> <tr> <td>Date Of Birth:- </td> <td>@Html.DisplayFor(model => model.DateOfBirth)</td> </tr> </table>
步骤 6
更新 _*Layout.cshtml*_ ** 页面以添加新的选项卡/超链接,用于用户登录、用户注册、用户信息和用户注销。
_Layout.cshtml ** 的代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - DemoIdentityAuthentication</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm
navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area=""
asp-controller="Home"
asp-action="Index">DemoIdentityAuthentication</a>
<button class="navbar-toggler" type="button"
data-toggle="collapse" data-target=".navbar-collapse"
aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area=""
asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area=""
asp-controller="Home" asp-action="Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area=""
asp-controller="Home" asp-action="Login">Login</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area=""
asp-controller="Home"
asp-action="UserInfo">User Information</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area=""
asp-controller="Home" asp-action="Logout">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2020 - DemoIdentityAuthentication - <a asp-area=""
asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@RenderSection("Scripts", required: false)
</body>
</html>
运行您的应用程序
成功运行应用程序后,您的应用程序的输出应如下所示:
- 单击 **用户信息** 选项卡以获取当前登录用户的信息,它将打开一个登录页面以登录用户。
**问题**:为什么它会要求登录?
**回答**:**[Authorize]** 属性限制了未经授权的请求访问数据/信息,并将用户重定向到登录页面以检查用户是否有效。在本例中,我们将此属性添加到了HomeController
的UserInformation
操作方法上。 - 在登录之前注册您的帐户。单击 **注册** 选项卡,然后根据以下屏幕提供用户信息:
- 成功注册后,将在浏览器中创建如下 Cookie:
-
现在,单击 **登录** 选项卡,然后输入如下屏幕所示的用户名和密码:
再次单击 **UserInfo** 选项卡,现在您可以在不要求登录的情况下找到用户信息的最终结果。
摘要
在本文中,我讨论了如何在 .NET Core 3.0 中使用内存数据库添加基于身份的身份验证。我们还创建了用户登录和注册表单,以便用户登录我们的应用程序以访问有用信息。我希望这能帮助读者理解如何在任何应用程序中实现基于身份的身份验证。请查找附件代码以获得更好的理解。
历史
- 2020 年 1 月 31 日:初始版本