
数字化时代,账户安全至关重要。传统的用户名密码认证方式存在诸多安全隐患,例如密码泄露、暴力破解等。短信验证码虽然增加了一层保护,但也面临被拦截、伪造的风险。为了进一步提升安全性,双因素认证(Two-Factor Authentication,简称2FA)应运而生。2FA要求用户提供两种不同类型的凭证:一是“你知道的东西”(如密码),二是“你拥有的东西”(如动态验证码)。本文将介绍如何使用Python实现基于时间的一次性密码(TOTP)算法的2FA认证。
双因素认证是一种安全机制,要求用户通过两种独立的验证方式才能访问账户。常见的组合包括:
1、知识因素:如密码、PIN码。
2、持有因素:如手机生成的动态验证码、硬件令牌(如U盾)。
动态验证码通常基于OTP算法生成,其中TOTP(基于时间的一次性密码)是最常用的标准之一。TOTP算法根据共享密钥和当前时间生成一个短暂有效的数字代码(通常为6位),有效时间一般为30秒。这种机制被广泛应用于Google Authenticator、Microsoft Authenticator等应用中。
PyOTP是一个Python库,支持TOTP和HOTP(基于计数器的一次性密码)算法的实现。以下将分步骤介绍如何使用PyOTP实现2FA。
首先,通过pip安装PyOTP库:
pip install pyotp在服务器端,需要生成一个随机的Base32编码密钥,用于与用户设备(如手机)配对:
import pyotp
# 生成随机Base32密钥secret_key = pyotp.random_base32()print("生成的密钥:", secret_key)输出示例:
生成的密钥: JBSWY3DPEHPK3PXP将密钥以二维码形式提供给用户扫描。可以使用 qrcode 库生成二维码:
import qrcode
# 构建OTP URI,便于Authenticator应用识别
totp_uri = pyotp.totp.TOTP(secret_key).provisioning_uri(name="user@example.com", issuer_name="MyApp")
print("OTP URI:", totp_uri)
# 生成二维码
qr = qrcode.make(totp_uri)
qr.save("totp_qr.png")
print("二维码已保存为 totp_qr.png")用户使用Google Authenticator等应用扫描二维码后,密钥将被保存到设备中。
在用户设备上,应用会根据密钥和当前时间生成动态验证码。在服务器端,也可以使用相同密钥生成验证码进行比对:
import time
# 使用密钥创建TOTP对象
totp = pyotp.TOTP(secret_key)
# 生成当前动态验证码
current_otp = totp.now()
print("当前动态验证码:", current_otp)当用户提交动态验证码时,服务器需要验证其有效性:
# 模拟用户提交的验证码
user_submitted_otp = "123456"
# 验证验证码
is_valid = totp.verify(user_submitted_otp)
if is_valid:
print("验证成功!")
else:
print("验证失败,请检查验证码或时间同步。")由于TOTP基于时间,验证码通常在30秒内有效。超过时间后验证将失败:
# 模拟延迟后验证
time.sleep(35)
is_valid_after_delay = totp.verify(user_submitted_otp)
print("延迟后验证结果:", is_valid_after_delay) # 输出 False除了TOTP,PyOTP也支持HOTP(基于计数器的一次性密码)。HOTP的验证码在每次验证后递增计数器:
# 创建HOTP对象
hotp = pyotp.HOTP(secret_key)
# 生成特定计数器的验证码
counter = 0
otp_at_counter = hotp.at(counter)
print(f"计数器 {counter} 的验证码:{otp_at_counter}")
# 验证验证码
is_hotp_valid = hotp.verify(otp_at_counter, counter)
print(f"验证结果:{is_hotp_valid}")以下是一个简单的Flask应用示例,演示如何集成2FA:
from flask import Flask, request, render_template_string
import pyotp
app = Flask(__name__)
# 模拟用户数据库
users = {
"alice": {
"password": "securepass123",
"secret_key": pyotp.random_base32() # 实际应用中应安全存储
}
}
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
otp = request.form['otp']
user = users.get(username)
if user and user['password'] == password:
totp = pyotp.TOTP(user['secret_key'])
if totp.verify(otp):
return f"登录成功!欢迎 {username}。"
else:
return "动态验证码错误。"
else:
return "用户名或密码错误。"
# 登录表单
form_html = """
<form method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
动态验证码:<input type="text" name="otp"><br>
<input type="submit" value="登录">
</form>
"""
return form_html
if __name__ == '__main__':
app.run(debug=True)通过PyOTP库,可以在应用中实现基于TOTP或HOTP的双因素认证。2FA显著提升了账户安全性,有效防止了因密码泄露导致的未授权访问。通过Python的灵活性和PyOTP的简便性,开发者可以快速为应用添加这一重要安全层。
“无他,惟手熟尔”!有需要的用起来!
如果你觉得这篇文章有用,欢迎点赞、转发、收藏、留言、推荐❤!
本文分享自 Nicholas与Pypi 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!