Python 谷歌令牌
python 实现google authenticator 认证
一、环境描述
windows开发环境
python: 3.6
所需安装包: pyotp qrcode Image
二、实现原理
1.使用pyotp 的python模块生成google auth 需要的密钥
2.根据密钥生成条形码图片
3.使用google authenticator 客户端扫描条形码,客户端根据时间及密钥经过算法生成6位数的验证码
4.平台二次认证通过对输入的验证码进行校验,校验也是基于时间和密钥
三、代码实现
3.1随机密钥生成
# a.安装模块包 pyotp
pip install pyotp
# b.密钥生成
import pyotp
gtoken = pyotp.random_base32(64) #获取随机密钥,存于用户表中,随机64位
3.2 图片二维码生成
# a. 安装模块包
pip install qrcode
qrcode 依赖 Image 这个包:
pip install Image
# b.根据用户名及密钥生成二维码
import os
import traceback
from qrcode import QRCode, constants
def get_qrcode(secret_key, username):
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
dirpath = os.path.join(BASE_DIR, 'mfa', 'static', 'image')
data = pyotp.totp.TOTP(secret_key).provisioning_uri(username, issuer_name="IAM MFA Code")
qr = QRCode(
version=1,
error_correction=constants.ERROR_CORRECT_L,
box_size=6,
border=4, )
try:
qr.add_data(data)
qr.make(fit=True)
img = qr.make_image()
filepath = dirpath + os.sep + secret_key + '.png'
print('filepath',filepath)
img.save(filepath) # 保存条形码图片
return True,filepath
except Exception as e:
traceback.print_exc()
return False,None
# c. 使用功能
result = get_qrcode(gtoken, 'supery')
print('result', result)
LWGOAZX5PQQLR34BOJRLVHHC4CRVFVXP3PGCYHWZ2PVKLRSJNCDWR6XPL4LAJRST
filepath D:\dev\PYSCRIPTS\xxx\mfa\static\image\LWGOAZX5PQQLR34BOJRLVHHC4CRVFVXP3PGCYHWZ2PVKLRSJNCDWR6XPL4LAJRST.png
result True
3.3 效验验证码正确性
# a. 下载好google authenticator客户端
客户扫描图片,前端页面验证用户名和密码后,显示对应的条形码图片
windows上打开图片后扫描二维码
D:\dev\PYSCRIPTS\xxx\mfa\static\image\LWGOAZX5PQQLR34BOJRLVHHC4CRVFVXP3PGCYHWZ2PVKLRSJNCDWR6XPL4LAJRST.png
实际生产环境通过页面直接显示该二维码图片,进行扫描
# b. 效验代码
import pyotp
def Google_Verify_Result(secret_key, verifycode):
t = pyotp.TOTP(secret_key)
result = t.verify(verifycode) # 对输入验证码进行校验,正确返回True
msg = result if result is True else False
return msg
# c. 使用功能
secret_key = 'LWGOAZX5PQQLR34BOJRLVHHC4CRVFVXP3PGCYHWZ2PVKLRSJNCDWR6XPL4LAJRST'
res = Google_Verify_Result(secret_key, 247724)
print('res', res) # res False || res True
四、完整代码
import os
import traceback
import pyotp
from qrcode import QRCode, constants
class GoogleAuthenticatorClient:
def __init__(self, secret_key=None):
self.secret_key = secret_key
def create_secret(self):
"""
生成google auth 需要的密钥
:return:
"""
self.secret_key = pyotp.random_base32(64)
return self.secret_key
def create_secret_qrcode(self, name=None, issuer_name=None, save_to_file=True):
"""
根据用户名及密钥生成二维码图片
:param name:用户名
:param issuer_name:发行人
:param save_to_file: 保存至文件
:return:
"""
data = pyotp.totp.TOTP(self.secret_key).provisioning_uri(name=name, issuer_name=issuer_name)
qr = QRCode(
version=1,
error_correction=constants.ERROR_CORRECT_L,
box_size=6,
border=4, )
try:
qr.add_data(data)
qr.make(fit=True)
img = qr.make_image()
if save_to_file:
base_dir = os.path.dirname(os.path.abspath(__file__))
dir_path = os.path.join(base_dir, 'static', 'image')
if not os.path.exists(dir_path):
os.makedirs(dir_path)
filepath = dir_path + os.sep + self.secret_key + '.png'
img.save(filepath) # 保存条形码图片
return True, filepath
else:
return img.get_image()
except Exception as e:
traceback.print_exc()
return False, None
def verify_code_func(self, verify_code):
t = pyotp.TOTP(self.secret_key)
result = t.verify(verify_code)
return result
if __name__ == '__main__':
secret_key = 'PU6PY6FWPVQ4BXE7ZP6X7YMVM3BH3ODS7SW53GL3LJPED7AAQUVF2EKP6AGNFFOX'
google_auth_ = GoogleAuthenticatorClient(secret_key=secret_key)
# 随机秘钥生成,使用动态开启口令验证,每次key
# secret = google_auth_.create_secret()
# print('秘钥', secret)
# # 生成图片二维码, save_to_file=True, 图片保存在本地, False 表示不保存,并显示在当前
image = google_auth_.create_secret_qrcode(name='slp', issuer_name='GoldBull', save_to_file=True)
print(image.show())
# 通过谷歌验证码器验证, 返回 True,表示通过, False 表示不通过
res = google_auth_.verify_code_func(verify_code='138914')
print(res)
Last updated