练习 - 配置多重身份验证
在上一单元中,你了解了 ASP.NET Core 标识如何为多重身份验证 (MFA) 实现基于时间的一次性密码 (TOTP)。 在本单元中,将自定义现有的“配置验证器应用”表单以提供包含注册密钥的 QR 码。
生成 QR 码
存在生成 QR 码的多种策略。 文档中的示例使用客户端 JavaScript 库。 但是,在本单元中,第三方 NuGet 包用于通过 C# 在服务器上生成 QR 码。 生成的 QR 码图像以 base-64 编码字符串的形式注入 HTML 占位符元素。
“添加 QR 码”服务
让我们生成在“配置验证器应用”窗体上生成 QR 码所需的一切。
在终端窗格中,安装
QRCoder
NuGet 包:dotnet add package QRCoder --version 1.6.0
在“资源管理器”窗格中,右键单击“服务”文件夹,并添加名为 QRCodeService.cs 的新文件。 添加以下代码:
using QRCoder; namespace RazorPagesPizza.Services; public class QRCodeService { private readonly QRCodeGenerator _generator; public QRCodeService(QRCodeGenerator generator) { _generator = generator; } public string GetQRCodeAsBase64(string textToEncode) { QRCodeData qrCodeData = _generator.CreateQrCode(textToEncode, QRCodeGenerator.ECCLevel.Q); var qrCode = new PngByteQRCode(qrCodeData); return Convert.ToBase64String(qrCode.GetGraphic(4)); } }
前面的代码:
- 使用构造函数注入访问库的
QRCodeGenerator
类的实例。 - 公开
GetQRCodeAsBase64
方法以返回 base-64 编码字符串。 传递给GetGraphic
的整数值决定了 QR 码维度。 在此情况下,生成的 QR 码由大小为四个像素的块组成。
- 使用构造函数注入访问库的
在 Program.cs 中,添加突出显示的行:
using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using RazorPagesPizza.Areas.Identity.Data; using Microsoft.AspNetCore.Identity.UI.Services; using RazorPagesPizza.Services; using QRCoder; var builder = WebApplication.CreateBuilder(args); var connectionString = builder.Configuration.GetConnectionString("RazorPagesPizzaAuthConnection"); builder.Services.AddDbContext<RazorPagesPizzaAuth>(options => options.UseSqlServer(connectionString)); builder.Services.AddDefaultIdentity<RazorPagesPizzaUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<RazorPagesPizzaAuth>(); // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddTransient<IEmailSender, EmailSender>(); builder.Services.AddSingleton(new QRCodeService(new QRCodeGenerator())); var app = builder.Build();
QRCodeService
在 Program.cs 内的 IoC 容器中注册为单一服务。
自定义多重身份验证
生成 QR 码后,可以将 QR 码嵌入“配置验证器应用”窗体中。
打开 Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs 并进行下列更改:
若要存储 QR 码的 base-64 字符串表示形式,请将以下属性添加到
EnableAuthenticatorModel
类:public class EnableAuthenticatorModel : PageModel { private readonly UserManager<RazorPagesPizzaUser> _userManager; private readonly ILogger<EnableAuthenticatorModel> _logger; private readonly UrlEncoder _urlEncoder; public string QrCodeAsBase64 { get; set; }
纳入
OnGetAsync
页处理程序中突出显示的更改:public async Task<IActionResult> OnGetAsync([FromServices] QRCodeService qrCodeService) { var user = await _userManager.GetUserAsync(User); if (user == null) { return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } await LoadSharedKeyAndQrCodeUriAsync(user); QrCodeAsBase64 = qrCodeService.GetQRCodeAsBase64(AuthenticatorUri); return Page(); }
在前面的页处理程序中,参数注入提供对
QRCodeService
单一服务的引用。若要解析对
QRCodeService
的引用,请将以下using
语句添加到文件顶部。 保存所做更改。using RazorPagesPizza.Services;
将突出显示的更改纳入到
GenerateQrCodeUri
方法。private string GenerateQrCodeUri(string email, string unformattedKey) { return string.Format( CultureInfo.InvariantCulture, AuthenticatorUriFormat, _urlEncoder.Encode("RazorPagesPizza"), _urlEncoder.Encode(email), unformattedKey); }
这将设置 TOTP 应用中密钥的显示名称。
在 Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml 中,进行以下突出显示的更改并保存:
<li> <p>Scan the QR Code or enter this key <kbd>@Model.SharedKey</kbd> into your two factor authenticator app. Spaces and casing do not matter.</p> <div class="alert alert-info">Learn how to <a href="https://go.microsoft.com/fwlink/?Linkid=852423">enable QR code generation</a>.</div> <div id="qrCode"> <img alt="embedded QR code" src="data:image/png;base64,@Model.QrCodeAsBase64" /> </div> <div id="qrCodeData" data-url="@Model.AuthenticatorUri"></div> </li>
前面的标记将 base-64 编码图像嵌入页中。
测试多重身份验证
在“配置验证器应用”窗体上,你已对 QR 码做了所有需要的更改。 现在,你可以轻松测试 MFA 功能。
确保已保存所有更改。
使用
dotnet run
生成并运行应用。导航到站点,并使用任一已注册用户登录(如果尚未登录)。 选择“Hello,[姓] [名]!”链接以导航到配置文件管理页面,然后选择“双因素身份验证”。
选择“添加验证器应用”按钮。
按照屏幕上的说明为此用户注册并验证身份验证器应用。
以 Android 上的 Microsoft Authenticator 为例,请按照以下步骤将该帐户添加到应用:
- 打开 Microsoft Authenticator 应用。
- 选择右上角的 kebab 菜单(竖省略号)。
- 选择“添加帐户”。
- 选择“其他帐户(Google、Facebook 等)”。
- 按照指示扫描 QR 码。
在“验证码”文本框中输入 TOTP 应用提供的验证码。
选择“验证”。
验证成功后,页面会显示“你的身份验证器应用已经过验证”横幅和一些恢复代码。
在 VS Code 中的“SQL Server”选项卡中,右键单击“RazorPagesPizza”数据库,然后选择“新建查询”。 输入以下查询,然后按 Ctrl+Shift+E 来运行它。
SELECT FirstName, LastName, Email, TwoFactorEnabled FROM dbo.AspNetUsers
对于已登录的用户,输出显示
TwoFactorEnabled
列等于1
。 由于未为其他已注册的用户启用多重身份验证,因此记录的列值为0
。在 Web 应用中,选择“注销”,然后使用同一用户重新登录。
在“验证器代码”文本框中输入 TOTP 验证器应用提供的验证码。 选择“登录”按钮。
选择“Hello, [姓] [名]!”。 然后,选择“双因素身份验证”选项卡。
由于已设置 Microsoft Authenticator,因此会显示以下按钮:
- 禁用 2FA
- 重置恢复代码
- 设置验证器应用
- 重置验证器应用
在 VS Code 的终端窗格中,按 Ctrl+C 来停止应用。
摘要
在本单元中,你添加了向“配置验证器应用”窗格生成 QR 码的功能。 在下一单元中,你可以了解如何使用标识来存储声明并应用授权策略。