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

如何在Perl Web应用中生成基于加密otpauth的浏览器内存式临时2FA二维码

Perl Web应用实现2FA二维码生成与展示(无服务器存储)

要实现兼容Google/Microsoft Authenticator的2FA二维码,且通过AJAX返回、仅在浏览器内存临时存储,可按以下步骤实现:

后端Perl处理逻辑

依赖模块

先安装所需Perl模块:

cpanm Authen::OATH GD::Barcode::QRcode CGI

(若使用PSGI/Plack框架,可替换CGI为Plack::Request等适配模块)

生成OTP Auth URI与二维码接口

以下是CGI示例,处理AJAX请求,生成标准otpauth URI并返回二维码的Base64编码(无需服务器存储图片文件):

#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use Authen::OATH;
use GD::Barcode::QRcode;
use MIME::Base64;

my $cgi = CGI->new;
print $cgi->header('application/json');

# 1. 生成或读取用户的2FA密钥(实际应用中需关联用户账号存储到数据库)
my $oath = Authen::OATH->new;
my $secret = $oath->create_secret(16); # 生成16字节=128位的安全密钥

# 2. 构建符合标准的otpauth URI
my $issuer = "MyWebApp"; # 你的应用名称
my $username = "user@example.com"; # 当前登录用户的账号
my $otpauth_uri = sprintf(
    "otpauth://totp/%s:%s?secret=%s&issuer=%s",
    uri_escape($issuer),
    uri_escape($username),
    $secret,
    uri_escape($issuer)
);

# 3. 生成QR码并转为Base64编码
my $qrcode = GD::Barcode::QRcode->new($otpauth_uri, { Ecc => 'M', Version => 4 });
my $img = $qrcode->plot;
my $img_base64 = encode_base64($img->png);

# 返回JSON数据,包含密钥(用于后续验证)和二维码Base64
print qq({"secret":"$secret","qrcode":"data:image/png;base64,$img_base64"});

# URI转义辅助函数
sub uri_escape {
    my $str = shift;
    $str =~ s/([^A-Za-z0-9\-_.~])/sprintf("%%%02X", ord($1))/eg;
    return $str;
}

前端AJAX请求与展示

前端发送AJAX请求到上述接口,获取Base64编码的二维码后,直接创建img元素渲染(仅存在浏览器内存,无服务器存储):

<!DOCTYPE html>
<html>
<body>
    <div id="qrcode-container"></div>
    <button onclick="generate2FAQR()">生成2FA二维码</button>

    <script>
        function generate2FAQR() {
            fetch('/cgi-bin/generate_2fa_qr.cgi')
                .then(response => response.json())
                .then(data => {
                    // 创建img元素,直接使用Base64数据URL
                    const img = document.createElement('img');
                    img.src = data.qrcode;
                    img.alt = "2FA验证二维码";
                    
                    // 清空容器并添加图片
                    const container = document.getElementById('qrcode-container');
                    container.innerHTML = '';
                    container.appendChild(img);

                    // 可选:临时保存密钥到本地存储(后续验证时需与后端存储的密钥比对)
                    localStorage.setItem('2fa_secret', data.secret);
                })
                .catch(error => console.error('生成二维码失败:', error));
        }
    </script>
</body>
</html>

关键注意事项

  • OTP URI标准:必须严格遵循otpauth://totp/Issuer:Username?secret=XXX&issuer=XXX格式,确保Authenticator应用能正确识别。
  • 无服务器存储:通过返回Base64编码的图片数据,直接在浏览器中渲染,服务器无需保存任何图片文件。
  • 密钥安全:后端必须将生成的$secret关联用户账号持久化存储,后续验证2FA验证码时需要用到该密钥;接口需通过HTTPS传输,避免密钥被窃听。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:15:05