为 ASP.NET Core 中的 TOTP 验证器应用启用 QR 码生成

ASP.NET Core 支持将验证器应用程序用于进行个人身份验证。 双因素身份验证 (2FA) 验证器应用使用基于时间的一次性密码算法 (TOTP),是行业推荐用于 2FA 的方法。 使用 TOTP 的 2FA 方法首选短信 2FA。 验证器应用提供 6-8 位代码,用户在确认他们的用户名和密码后必须输入该代码。 通常,验证器应用安装在智能手机上。

ASP.NET Core Web 应用模板支持验证器,但不提供对 QR 码生成的支持。 QR 码生成器可简化 2FA 的设置。 本文档将指导你完成将 QR 码生成添加到 2FA 配置页面。

使用 GoogleFacebook 等外部身份验证提供程序时不会进行双因素身份验证。 外部登录受外部登录提供程序提供的机制的保护。 例如,假设 Microsoft 身份验证提供程序需要硬件密钥或其他 2FA 方法。 如果默认模板强制执行“本地”2FA,那么用户需要满足两个 2FA 方法,这不是常用的方案。

将 QR 码添加到 2FA 配置页面

这些说明使用来自 https://davidshimjs.github.io/qrcodejs/ 存储库的 qrcode.js

  • qrcode.js JavaScript 库下载到项目中的 wwwroot\lib 文件夹。
  • 按照搭建 Identity 的基架中的说明生成 /Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml
  • /Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml 中,找到文件末尾的 Scripts 节:
@section Scripts {
    @await Html.PartialAsync("_ValidationScriptsPartial")
}
  • wwwroot/js 中新建名为 qr.js 的一个 JavaScript 文件,并添加以下代码以生成 QR 码:
window.addEventListener("load", () => {
  const uri = document.getElementById("qrCodeData").getAttribute('data-url');
  new QRCode(document.getElementById("qrCode"),
    {
      text: uri,
      width: 150,
      height: 150
    });
});
  • 更新 Scripts 部分以添加对之前下载的 qrcode.js 库的引用。
  • 通过调用添加 qr.js 文件以生成 QR 码:
@section Scripts {
    @await Html.PartialAsync("_ValidationScriptsPartial")

    <script type="text/javascript" src="~/lib/qrcode.js"></script>
    <script type="text/javascript" src="~/js/qr.js"></script>
}
  • 删除链接到这些说明的段落。

运行应用,并确保可以扫描 QR 码并验证验证器证明的代码。

更改 QR 码中的站点名称

QR 码中的站点名称取自你在最初创建项目时选择的项目名称。 可以通过在 /Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs 中查找 GenerateQrCodeUri(string email, string unformattedKey) 方法来更改站点名称。

模板中的默认代码如下所示:

private string GenerateQrCodeUri(string email, string unformattedKey)
{
    return string.Format(
        AuthenticatorUriFormat,
        _urlEncoder.Encode("Razor Pages"),
        _urlEncoder.Encode(email),
        unformattedKey);
}

string.Format 的调用中的第二个参数是你的站点名称,取自你的解决方案名称。 它可以更改为任何值,但必须始终是 URL 编码的。

使用不同的 QR 码库

可以使用你的首选库来取代 QR 码库。 HTML 包含一个 qrCode 元素,可以通过你的库所提供的任何机制将 QR 码放在该元素中。

QR 码的格式正确的 URL 位于:

  • 模型的 AuthenticatorUri 属性中。
  • qrCodeData 元素中的 data-url 属性中。

TOTP 客户端和服务器时间倾斜

TOTP(基于时间的一次性密码)身份验证依赖于具有准确时间的服务器和验证器设备。 令牌仅持续 30 秒。 如果 TOTP 2FA 登录失败,请检查服务器时间是否准确,最好同步到准确的 NTP 服务。