一、Nuget依赖包安装
需要安装一下Nuget包: Opt.NET
和 QRCoder
两个依赖包。
二、QrCode生成工具类
ZyhQrCodeGeneratorBase.cs,该文件为基础文件,其中并未引用System.Drawing,具体其中的类属性和初始化构造方法可以根据自身情况修改。
# ZyhQrCodeGeneratorBase.cs
using OtpNet;
using QRCoder;
using static QRCoder.SvgQRCode;
namespace Zyh.Common.Security
{
/// <summary>
/// QrCode助手
/// </summary>
public class ZyhQrCodeGeneratorBase
{
protected string SECRET_BASE = "RLX5E3R2OHRPJWNHSYTAFVM4IARIOIPO";
protected int TIME_SPAN = 30;
protected int PWD_LENGTH = 6;
protected OtpHashMode HASH_MODE = OtpHashMode.Sha512;
protected readonly Totp _totp;
protected QRCodeData _qrCodeData;
public ZyhQrCodeGeneratorBase(string user = "zyh@test.com", string issuer = "Zyh Co")
{
using QRCodeGenerator qRCodeGenerator = new QRCodeGenerator();
_qrCodeData = qRCodeGenerator.CreateQrCode(
new OtpUri(
schema: OtpType.Totp,
secret: SECRET_BASE,
user: user,
issuer: issuer,
algorithm: OtpHashMode.Sha512
).ToString(),
QRCodeGenerator.ECCLevel.Q
);
_totp = new Totp(secretKey: Base32Encoding.ToBytes(SECRET_BASE), step: TIME_SPAN, mode: HASH_MODE, totpSize: PWD_LENGTH);
}
/// <summary>
/// 适用于 Web、Retro 和 Console 环境。
/// 通过使用此编码器,您可以获得一个编码为字符串的 QR 码,该字符串仅由字符构建而成。
/// 默认情况下,使用 UTF-8 块符号。
/// </summary>
/// <returns></returns>
public string GetAsciiQRCodeString()
{
AsciiQRCode qrCode = new AsciiQRCode(_qrCodeData);
return qrCode.GetGraphic(
repeatPerModule: 1, // 每个模块重复的 darkColorString/whiteSpaceString 的数量。必须为 1 或更大
darkColorString: "#000000",
whiteSpaceString: "#FFFFFF",
drawQuietZones: true, // 整个QR码周围绘制白色边框
endOfLine: "\n" // 行尾分隔符
);
}
/// <summary>
/// 通常在 Web 和数据库环境中非常有用。
/// 您可以将 Base64 图像嵌入到 html 代码中,通过 HTTP 请求轻松传输它们或将它们轻松写入数据库。
/// </summary>
/// <param name="type"></param>
/// <param name="bitmap"></param>
/// <returns></returns>
public string GetBase64QRCodeString(Base64QRCode.ImageType type = Base64QRCode.ImageType.Png)
{
Base64QRCode qrCode = new Base64QRCode(_qrCodeData);
return qrCode.GetGraphic(
pixelsPerModule: 20, // 绘制每个黑白模块的像素大小
darkColorHtmlHex: "#000000",
lightColorHtmlHex: "#FFFFFF",
drawQuietZones: true, // 整个QR码周围绘制白色边框
imgType: type // Base64 字符串编码的图片格式
);
}
/// <summary>
/// GetBase64QRCodeString方法的扩展,转换为HTML
/// </summary>
/// <param name="type"></param>
/// <param name="bitmap"></param>
/// <returns></returns>
public string GetBase64QRCodeStringExtension(Base64QRCode.ImageType type = Base64QRCode.ImageType.Png)
{
string qrCodeImageAsBase64 = GetBase64QRCodeString(type);
return $"<img alt=\"Embedded QR Code\" src=\"data:image/{type.ToString().ToLower()};base64,{qrCodeImageAsBase64}\" />";
}
/// <summary>
/// 当使用 QRCoder 的 PCL 版本时(例如在移动项目中),这是除 PngByteQRCode 之外唯一可用的渲染器。
/// 它以字节数组的形式返回 QR 码,其中包含位图图形。
/// 由于许多提供 PCL 库的平台具有不同的 Bitmap 类实现,但几乎任何平台都可以从 byte[] 创建图像,因此这是跨平台处理图像的某种方法。
/// </summary>
/// <returns></returns>
public byte[] GetBitmapByteQRCodeBytes()
{
BitmapByteQRCode qrCode = new BitmapByteQRCode(_qrCodeData);
return qrCode.GetGraphic(
pixelsPerModule: 20,
darkColorHtmlHex: "#CCCCCC",
lightColorHtmlHex: "#444444"
);
}
/// <summary>
/// 当使用 QRCoder 的 PCL 版本时(例如,在移动项目中),除了 BitmapByteQRCode 之外,这是可用的渲染器。
/// 它将 QR 码作为包含 PNG 图形的字节数组返回。
/// 由于许多提供 PCL 库的平台具有不同的 Imaging 类实现,但几乎任何平台都可以从 byte[] 创建图像(或将字节数组写入文件),因此这是跨平台处理图像的某种方法。
/// </summary>
/// <param name="dark"></param>
/// <param name="light"></param>
/// <returns></returns>
public byte[] GetPngByteQRCodeBytes(byte[] dark, byte[] light)
{
PngByteQRCode qrCode = new PngByteQRCode(_qrCodeData);
return qrCode.GetGraphic(
pixelsPerModule: 20,
darkColorRgba: dark, // RGB(A) 数组
lightColorRgba: light, // RGB(A) 数组
drawQuietZones: true // 整个QR码周围绘制白色边框
);
}
/// <summary>
/// 如果您想打印大尺寸的 QR 码或处理可扩展(从屏幕尺寸的角度来看)Web 应用程序,请使用此选项。SvgQRCode 返回一个可缩放的矢量图形,该图形本质上永远不会变得模糊。
/// </summary>
/// <returns></returns>
public string GetSvgQRCodeBytes(SvgLogo? logo = null)
{
SvgQRCode qrCode = new SvgQRCode(_qrCodeData);
return qrCode.GetGraphic(
pixelsPerModule: 20,
darkColorHex: "#000000",
lightColorHex: "#FFFFFF",
drawQuietZones: true,
sizingMode: SizingMode.WidthHeightAttribute,
logo: logo
);
}
public bool VertyQrCode(string userTotp)
{
return _totp.VerifyTotp(userTotp, out _);
}
}
}
ZyhQrCodeGeneratorExtension.cs,该扩展类方法中须引用System.Drawing方法进行参数绑定,如果上述文件方法无法实现相关逻辑,可在该文件中进行扩展。
# ZyhQrCodeGeneratorExtension.cs
using QRCoder;
namespace Zyh.Common.Security
{
public class ZyhQrCodeGeneratorExtension : ZyhQrCodeGeneratorBase
{
public ZyhQrCodeGeneratorExtension() : base() { }
/// <summary>
/// 如果需要基于像素的图像 (=Bitmap) 并且正在使用 .NET Framework,请使用它。
/// 如果您想在应用程序中显示 QR 码、将 QR 码保存为图像文件或将 QR 码作为下载提供,请使用它。
/// </summary>
/// <returns></returns>
public System.Drawing.Bitmap? GetQrCodeBitmap(System.Drawing.Bitmap? bitmap = null)
{
QRCode qrCode = new QRCode(_qrCodeData);
if (bitmap != null)
{
return qrCode.GetGraphic(
pixelsPerModule: 20, // 绘制每个黑白模块的像素大小
darkColor: System.Drawing.Color.Black, // 黑色模块颜色
lightColor: System.Drawing.Color.White, // 白色模块颜色
icon: bitmap, // icon图标
iconSizePercent: 15, // 图标占比 1-99
iconBorderWidth: 6, // 图标周围绘制的边框的宽度,最小1
drawQuietZones: true, // 整个QR码周围绘制白色边框
iconBackgroundColor: null // 图标背景颜色,为null则使用白色模块值,仅呈现图标背景,只有在icon!=null和iconBorderWidth>0才生效
);
}
else
{
// 绘制每个黑白模块的像素大小,黑色模块颜色,白色模块颜色,整个QR码周围绘制白色边框
return qrCode.GetGraphic(20, "#000000", "#FFFFFF", true);
}
}
/// <summary>
/// 通常在 Web 和数据库环境中非常有用。
/// 您可以将 Base64 图像嵌入到 html 代码中,通过 HTTP 请求轻松传输它们或将它们轻松写入数据库。
/// </summary>
/// <param name="type"></param>
/// <param name="bitmap"></param>
/// <returns></returns>
public string GetBase64QRCodeStringWithBitmap(Base64QRCode.ImageType type = Base64QRCode.ImageType.Png, System.Drawing.Bitmap? bitmap = null)
{
Base64QRCode qrCode = new Base64QRCode(_qrCodeData);
if (bitmap != null)
{
return qrCode.GetGraphic(
pixelsPerModule: 20, // 绘制每个黑白模块的像素大小
darkColor: System.Drawing.Color.Black,
lightColor: System.Drawing.Color.White,
icon: bitmap, // icon图标
iconSizePercent: 15, // 图标占比 1-99
iconBorderWidth: 6, // 图标周围绘制的边框的宽度,最小1
drawQuietZones: true, // 整个QR码周围绘制白色边框
imgType: type // Base64 字符串编码的图片格式
);
}
else
{
return qrCode.GetGraphic(
pixelsPerModule: 20, // 绘制每个黑白模块的像素大小
darkColorHtmlHex: "#000000",
lightColorHtmlHex: "#FFFFFF",
drawQuietZones: true, // 整个QR码周围绘制白色边框
imgType: type // Base64 字符串编码的图片格式
);
}
}
/// <summary>
/// GetBase64QRCodeString方法的扩展,转换为HTML
/// </summary>
/// <param name="type"></param>
/// <param name="bitmap"></param>
/// <returns></returns>
public string GetBase64QRCodeStringWithBitmapExtension(Base64QRCode.ImageType type = Base64QRCode.ImageType.Png, System.Drawing.Bitmap? bitmap = null)
{
string qrCodeImageAsBase64 = GetBase64QRCodeStringWithBitmap(type, bitmap);
return $"<img alt=\"Embedded QR Code\" src=\"data:image/{type.ToString().ToLower()};base64,{qrCodeImageAsBase64}\" />";
}
}
}
三、QrCode工具类调用示例
using Zyh.Common.Security;
public ZyhQrCodeGeneratorExtension _qrCodeGenerator = new();
public string GetBase64Qrcode() {
return _qrCodeGenerator .GetBase64QRCodeString();
}
public bool VertyQrcode(string code) {
return _qrCodeGenerator.VertyQrCode(code);
}