Security
2FA完全指南 - TOTP、短信、硬件密钥对比与实现
双因素认证(2FA)的类型和安全级别。TOTP应用、短信、硬件密钥的优缺点及开发者实现指南。
Toolypet Team
Development Team
2FA完全指南:是什么、为什么、怎么做
密码一旦泄露,就完了。
截至2024年,泄露的密码已超过100亿个。无论密码多强,在数据库被黑面前都无能为力。
**2FA(双因素认证)**即使密码泄露也能保护你的账户。
什么是2FA?
2FA(Two-Factor Authentication)是使用两种因素进行认证的方式。
认证的三要素
| 要素 | 含义 | 示例 |
|---|---|---|
| 知识 | 你知道的 | 密码、PIN码 |
| 拥有 | 你拥有的 | 手机、硬件密钥 |
| 固有 | 你是谁 | 指纹、面部 |
2FA组合其中两种要素。
密码(知识) + TOTP应用(拥有) = 2FA
PIN码(知识) + 指纹(固有) = 2FA
为什么需要2FA
| 攻击类型 | 仅密码 | 使用2FA |
|---|---|---|
| 钓鱼 | 被突破 | 延迟或阻止 |
| 暴力破解 | 可能被突破 | 阻止 |
| 数据库泄露 | 被突破 | 阻止 |
| 偷窥 | 被突破 | 阻止 |
2FA类型对比
1. 短信认证
登录尝试 → 手机收到6位验证码 → 输入
| 优点 | 缺点 |
|---|---|
| 无需额外应用 | 易受SIM卡交换攻击 |
| 用户熟悉 | 易受钓鱼攻击 |
| 部署快速 | 需要网络信号 |
安全等级:2/5(低)
短信容易受到SIM卡交换攻击。攻击者欺骗运营商复制SIM卡后,可以拦截短信。
2. TOTP应用(推荐)
基于时间的一次性密码
每30秒生成新代码
应用示例:Google Authenticator、Authy、1Password
| 优点 | 缺点 |
|---|---|
| 离线可用 | 需要安装应用 |
| 免疫SIM卡交换 | 恢复码丢失风险 |
| 免费 | 设备丢失时有问题 |
安全等级:4/5(高)
3. 硬件安全密钥
通过USB或NFC进行物理认证
示例:YubiKey、Google Titan Key
| 优点 | 缺点 |
|---|---|
| 完全防止钓鱼 | 有成本(30-70美元) |
| 最强安全性 | 物理丢失风险 |
| 使用简单 | 并非所有服务都支持 |
安全等级:5/5(最高)
4. 应用推送认证
登录尝试 → 应用收到推送通知 → 批准/拒绝
示例:Microsoft Authenticator、Duo
| 优点 | 缺点 |
|---|---|
| 使用方便 | 需要联网 |
| 防钓鱼 | 依赖应用 |
安全等级:4/5(高)
TOTP工作原理
概念
TOTP = HMAC-SHA1(密钥, 时间) → 6位数字
- 服务器和应用共享一个密钥(secret)
- 将当前时间除以30秒
- 用密钥 + 时间生成哈希
- 从哈希中提取6位数字
由于服务器和应用使用相同的时间和密钥,因此生成相同的代码。
二维码内容
otpauth://totp/服务:账户?secret=BASE32密钥&issuer=服务
otpauth://totp/GitHub:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=GitHub
扫描二维码后,应用会保存这些信息。
开发者TOTP实现指南
Node.js示例(otplib)
const { authenticator } = require('otplib');
// 1. 生成密钥(用户注册时)
const secret = authenticator.generateSecret();
// "JBSWY3DPEHPK3PXP"
// 2. 生成二维码URL
const otpauthUrl = authenticator.keyuri(
'user@example.com',
'MyApp',
secret
);
// 使用QR库生成图片
// 3. 验证代码(登录时)
const userToken = "123456"; // 用户输入
const isValid = authenticator.verify({ token: userToken, secret });
if (isValid) {
console.log("认证成功");
} else {
console.log("无效代码");
}
Python示例(pyotp)
import pyotp
# 1. 生成密钥
secret = pyotp.random_base32()
# 2. 二维码URL
totp = pyotp.TOTP(secret)
url = totp.provisioning_uri(name='user@example.com', issuer_name='MyApp')
# 3. 验证代码
user_token = "123456"
is_valid = totp.verify(user_token)
安全注意事项
// 允许时间偏差(前后30秒)
authenticator.options = {
window: 1 // 允许-30秒到+30秒
};
// 防止重用
// 保存已使用的代码,阻止相同代码重用
const usedCodes = new Set();
function verifyOnce(token, secret) {
if (usedCodes.has(token)) return false;
if (authenticator.verify({ token, secret })) {
usedCodes.add(token);
// 60秒后删除(内存管理)
setTimeout(() => usedCodes.delete(token), 60000);
return true;
}
return false;
}
恢复码管理
如果丢失2FA,就无法访问账户。务必提供恢复码。
生成
const crypto = require('crypto');
function generateRecoveryCodes(count = 10) {
const codes = [];
for (let i = 0; i < count; i++) {
// 8位大写字母+数字
const code = crypto.randomBytes(4).toString('hex').toUpperCase();
codes.push(`${code.slice(0,4)}-${code.slice(4)}`);
}
return codes;
}
// ["A3F8-B2C1", "D4E5-F6G7", ...]
存储
// 恢复码哈希后存储(推荐bcrypt)
const bcrypt = require('bcrypt');
async function storeRecoveryCodes(codes) {
const hashedCodes = await Promise.all(
codes.map(code => bcrypt.hash(code, 10))
);
// 将hashedCodes存入数据库
}
// 使用时验证
async function useRecoveryCode(inputCode, hashedCodes) {
for (const hashed of hashedCodes) {
if (await bcrypt.compare(inputCode, hashed)) {
// 删除代码(一次性使用)
return true;
}
}
return false;
}
用户体验(UX)建议
1. 引导设置2FA
首次登录后:"为了账户安全,请设置2FA"
敏感操作前:"此操作需要2FA验证"
2. 分步指引
第1步:安装认证应用(提供Google Authenticator链接)
第2步:扫描二维码
第3步:输入6位代码确认
第4步:保存恢复码(重点强调!)
3. 强调恢复码
警告:请将这些代码保存在安全的地方。
如果丢失,将无法恢复账户。
[ 下载代码 ] [ 复制代码 ]
常见问题
Q:应该完全避免使用短信2FA吗?
A:虽然比TOTP弱,但比没有强得多。尽量使用TOTP或硬件密钥,但如果服务只支持短信,一定要启用。
Q:如果丢失了装有2FA应用的手机怎么办?
A:使用恢复码登录后重新设置2FA。这就是为什么必须另外安全保存恢复码的原因。
Q:可以注册备用2FA吗?
A:可以,在同一账户注册多个设备(如果服务支持),或者在首次扫描二维码时同时在多个设备上扫描。
总结
| 2FA类型 | 安全性 | 便利性 | 推荐 |
|---|---|---|---|
| 短信 | 2/5 | 5/5 | 最后选择 |
| TOTP应用 | 4/5 | 4/5 | 一般推荐 |
| 硬件密钥 | 5/5 | 3/5 | 高安全需求 |
| 应用推送 | 4/5 | 5/5 | 企业使用 |
至少使用TOTP。仅靠密码是不够的。
相关工具
2FAMFATOTP认证安全开发
关于作者
Toolypet Team
Development Team
The Toolypet Team creates free, privacy-focused web tools for developers and designers. All tools run entirely in your browser with no data sent to servers.
Web DevelopmentCSS ToolsDeveloper ToolsSEOSecurity