練習 - 設定多重要素驗證

已完成

在上一個單元中,您已了解 ASP.NET Core 身分識別如何實作時間型單次密碼 (TOTP),以進行多重要素驗證 (MFA)。 在此單元中,您將自訂現有的 [設定驗證器應用程式] 表單,以提供包含註冊金鑰的 QR 代碼。

產生 QR 代碼

有多個策略可產生 QR 代碼。 本文件中的範例使用 client-side JavaScript library。 不過,在此單元中,會使用協力廠商 NuGet 套件,在伺服器上使用 C# 產生 QR 代碼。 產生的 QR 代碼影像會插入 HTML 預留位置元素中,作為 base-64 編碼的字串。

新增 QR 代碼服務

請建置您在設定驗證器應用程式表單上產生 QR 代碼所需的一切。

  1. 在終端窗格中,安裝 QRCoder NuGet 套件:

    dotnet add package QRCoder --version 1.6.0
    
  2. 在 [Explorer] 窗格中,用滑鼠右鍵按一下 [服務] 資料夾,並新增名為 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 代碼將由大小為四個像素的方框組成。
  3. 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();
    

    QRCodeServiceProgram.cs 中,註冊為 IoC 容器內的單一服務。

自訂多重要素驗證

現在您可以產生 QR 代碼,將 QR 代碼內嵌至 [設定驗證器應用程式] 表單。

  1. 開啟 Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs,然後進行下列變更:

    1. 若要儲存 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; }    
      
    2. 將反白顯示的變更併入 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 單一服務的參考。

    3. 若要解析對 QRCodeService 的參考,請將下列 using 陳述式新增至檔案頂端。 儲存您的變更。

      using RazorPagesPizza.Services;
      
    4. 將醒目提示的變更納入 GenerateQrCodeUri 方法。

      private string GenerateQrCodeUri(string email, string unformattedKey)
      {
          return string.Format(
              CultureInfo.InvariantCulture,
              AuthenticatorUriFormat,
              _urlEncoder.Encode("RazorPagesPizza"),
              _urlEncoder.Encode(email),
              unformattedKey);
      }
      

      這會在 TOTP 應用程式中設定金鑰的顯示名稱。

  2. 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 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 功能。

  1. 請確定您已儲存所有變更。

  2. 使用 dotnet run 建置並執行應用程式。

  3. 如果您尚未登入,請瀏覽至網站,並使用其中一個已註冊的使用者登入。 選取 [名字] [姓氏] 您好!連結以導覽至設定檔管理頁面,然後選取 [雙重要素驗證]

  4. 選取 [新增驗證器應用程式] 按鈕。

  5. 依照畫面上的指示,為此使用者註冊並驗證您的驗證器應用程式。

    使用 Android 上的 Microsoft Authenticator 作為範例,依照下列步驟將帳戶新增至應用程式:

    1. 開啟 Microsoft Authenticator 應用程式。
    2. 選取右上方的烤肉串功能表 (垂直省略符號)。
    3. 選取 [新增帳戶]
    4. 選取 [其他帳戶 (Google、Facebook 等)]
    5. 依指示掃描 QR 代碼。
  6. 在 [驗證碼] 文字方塊中,輸入您的 TOTP 應用程式所提供的驗證碼。

  7. 選取 [驗證]

    驗證成功後,頁面上會顯示 [您的驗證器應用程式已通過驗證] 橫幅和一些復原碼。

  8. 在 VS Code 的 [SQL Server] 索引標籤中,以滑鼠右鍵按一下 [RazorPagesPizza] 資料庫,並選取 [新查詢]。 輸入下列查詢,然後按 Ctrl+Shift+E 以執行查詢。

    SELECT FirstName, LastName, Email, TwoFactorEnabled
    FROM dbo.AspNetUsers
    

    針對已登入的使用者,輸出會顯示 TwoFactorEnabled 資料行等於 1。 其他已註冊的使用者尚未啟用多重要素驗證,因此記錄的資料行值為 0

  9. 在 Web 應用程式中,選取 [登出],然後使用相同的使用者重新登入。

  10. 在 [驗證器代碼] 文字方塊中,輸入 TOTP 驗證器應用程式的驗證碼。 選取 [登入] 按鈕。

  11. 選取 Hello, [First name] [Last name]!。 接著,選取 [雙重要素驗證] 索引標籤。

    由於已設定 Microsoft Authenticator,因此會出現下列按鈕:

    • 停用 2FA
    • 重設復原碼
    • 設定驗證器應用程式
    • 重設驗證器應用程式
  12. 在 VS Code 的終端窗格中,按 Ctrl+C 以停止應用程式。

摘要

在此單元中,您已在設定驗證器應用程式表單中新增了產生 QR 代碼的功能。 在下一個單元中,您將了解如何使用 Identity 來儲存宣告並套用授權原則。