You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Blazor .NET 8的Razor组件中生成验证器二维码

在Blazor(.NET 8)Identity组件中生成2FA验证器二维码

使用.NET 8的Identity Razor组件时,官方提供的二维码生成方案针对CSHTML页面设计,依赖页面load事件触发JavaScript,但Blazor组件中该事件不会触发;同时OnInitializedAsync阶段无法执行JavaScript操作,若OnAfterRenderAsync未被调用,也无法通过常规方式生成二维码。以下是两种可行的解决方法:

方法一:通过JavaScript在前端生成二维码

1. 获取2FA验证器URI

在Blazor组件的代码逻辑中,借助UserManager获取Identity提供的2FA验证器URI:

private string? _authenticatorUri;
private bool _hasRenderedQr;

[Inject]
private UserManager<IdentityUser> UserManager { get; set; } = default!;
[Inject]
private IJSRuntime JSRuntime { get; set; } = default!;

protected override async Task OnInitializedAsync()
{
    var user = await UserManager.GetUserAsync(User);
    if (user != null)
    {
        var authKey = await UserManager.GetAuthenticatorKeyAsync(user);
        var issuer = Uri.EscapeDataString(UserManager.Options.Tokens.AuthenticatorIssuer);
        var userEmail = Uri.EscapeDataString(user.Email ?? string.Empty);
        _authenticatorUri = $"otpauth://totp/{issuer}:{userEmail}?secret={authKey}&issuer={issuer}";
    }
}

2. 在组件渲染完成后调用JS生成二维码

Blazor中只有组件渲染完成后才能操作DOM,因此在OnAfterRenderAsync中执行JS调用,添加标记避免重复执行:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender && !_hasRenderedQr && !string.IsNullOrEmpty(_authenticatorUri))
    {
        await JSRuntime.InvokeVoidAsync("generate2FaQr", "qr-container", _authenticatorUri);
        _hasRenderedQr = true;
    }
}

3. 添加QR生成的JS代码

在wwwroot/js/2fa-qr.js中写入以下代码(需提前下载qrcode.min.js到wwwroot/js目录):

function generate2FaQr(containerId, authUri) {
    const container = document.getElementById(containerId);
    if (!container) return;
    
    new QRCode(container, {
        text: authUri,
        width: 160,
        height: 160,
        colorDark: "#000",
        colorLight: "#fff",
        correctLevel: QRCode.CorrectLevel.H
    });
}

在index.html(WebAssembly)或_Layout.cshtml(Server)中引入JS文件:

<script src="~/js/qrcode.min.js"></script>
<script src="~/js/2fa-qr.js"></script>

4. 在组件中添加二维码容器

在.razor组件的标记部分添加用于承载二维码的DOM元素:

@if (!string.IsNullOrEmpty(_authenticatorUri))
{
    <div id="qr-container" class="mt-3"></div>
}

方法二:后端生成二维码图片(无需JavaScript)

1. 安装依赖包

安装NuGet包ZXing.Net,用于后端生成QR码图片。

2. 生成Base64格式的二维码图片

在Blazor组件代码中生成二维码并转换为Base64格式:

private string? _qrCodeBase64;

[Inject]
private UserManager<IdentityUser> UserManager { get; set; } = default!;

protected override async Task OnInitializedAsync()
{
    var user = await UserManager.GetUserAsync(User);
    if (user != null)
    {
        var authKey = await UserManager.GetAuthenticatorKeyAsync(user);
        var issuer = Uri.EscapeDataString(UserManager.Options.Tokens.AuthenticatorIssuer);
        var userEmail = Uri.EscapeDataString(user.Email ?? string.Empty);
        var authUri = $"otpauth://totp/{issuer}:{userEmail}?secret={authKey}&issuer={issuer}";

        // 生成QR码像素数据
        var writer = new ZXing.BarcodeWriterPixelData
        {
            Format = ZXing.BarcodeFormat.QR_CODE,
            Options = new ZXing.Common.EncodingOptions
            {
                Width = 160,
                Height = 160,
                Margin = 1
            }
        };
        var pixelData = writer.Write(authUri);

        // 转换为Base64格式的PNG图片
        using var ms = new MemoryStream();
        using var bitmap = new System.Drawing.Bitmap(pixelData.Width, pixelData.Height);
        var bitmapData = bitmap.LockBits(
            new System.Drawing.Rectangle(0, 0, pixelData.Width, pixelData.Height),
            System.Drawing.Imaging.ImageLockMode.WriteOnly,
            System.Drawing.Imaging.PixelFormat.Format32bppRgb);
        System.Runtime.InteropServices.Marshal.Copy(pixelData.Pixels, 0, bitmapData.Scan0, pixelData.Pixels.Length);
        bitmap.UnlockBits(bitmapData);
        bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        _qrCodeBase64 = $"data:image/png;base64,{Convert.ToBase64String(ms.ToArray())}";
    }
}

3. 在组件中显示二维码图片

在.razor组件的标记部分添加图片标签:

@if (!string.IsNullOrEmpty(_qrCodeBase64))
{
    <img src="@_qrCodeBase64" alt="2FA验证器二维码" class="mt-3" />
}

内容的提问来源于stack exchange,提问作者Patrick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 14:56:20