如何在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
相关产品推荐
相关产品推荐

