pythonのライブラリである pyotp を使うと簡単にワンタイムパスワードが実装できます。
-
まずは環境を構築します
$ apt-get update $ apt-get install -y curl wget vim $ python3 python3.12-venv $ python3 -m venv /work/python $ /work/python/bin/pip install flask $ /work/python/bin/pip install pyotp $ /work/python/bin/pip install qrcode $ /work/python/bin/pip install pillow $ /work/python/bin/pip install BytesIO
-
アプリを作成します。本来はキー情報はDBに格納が必要ですが、今回はJSONファイルに書き出しています。
from flask import Flask, render_template, request import pyotp import qrcode import os import json import base64 from io import BytesIO app = Flask(__name__) # 初期画面 @app.route('/index') def index(): return render_template('index.html') # 登録画面 @app.route('/regist', methods=['POST']) def regist(): userid = request.form['userid'] key = pyotp.random_base32() with open('/work/data/test.json') as f: d = json.load(f) d[userid] = key data_str = json.dumps(d) with open('/work/data/test.json', mode='w') as f: f.write(data_str) totp = pyotp.TOTP(key) qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=5, border=2, ) qr.add_data(totp.provisioning_uri(name=userid, issuer_name="KstoneriverSampleApp")) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white") buffered = BytesIO() img.save(buffered, format="JPEG") img_str = base64.b64encode(buffered.getvalue()).decode("ascii") return render_template('regist.html', img=img_str, userid=userid) # 登録結果 @app.route('/validate', methods=['POST']) def validate(): userid = request.form['userid'] otp = request.form['otp'] with open('/work/data/test.json') as f: d = json.load(f) key = d[userid] totp = pyotp.TOTP(key) result = totp.verify(otp) if result: ret_str = "Success!!" else: ret_str = "Failed..." return render_template('result.html', ret = ret_str) if __name__ == '__main__': app.run(host="0.0.0.0", port=5000, debug=True)
-
実行します
/work/python/bin/python app.py