什么是雙因素驗證 2FA,如何用 Python 實現?
傳統的用戶名密碼方式,容易泄漏,并不安全。
你說,加上短信驗證碼不就安全了,其實短信驗證碼也是不安全的,容易被攔截和偽造,SIM 卡也可以克隆,已經有案例,先偽造身份證,再申請一模一樣的手機號碼,把錢轉走。
因此就有了 Two-factor authentication,簡稱 2FA,也就是雙因素驗證。最常見的就是用戶名密碼,再加一個動態(tài)碼。動態(tài)碼通常由隨身攜帶的移動設備上生成,比如 U 盾、手機。
動態(tài)碼最常見的實現算法就是 One-Time Password(OTP),是基于時間的一次性密碼,它是公認的可靠解決方案,已經寫入國際標準 RFC6238。比如我們最常用的 Google Authenticator,就是 OTP。
那么,知道了 2FA,接下來應該考慮的事,就是如何讓你用 Python 寫的網站實現 2FA。
輪子其實已經有了,那就是 PyOTP,結合自己的理解,分享一下它的用法。
1.安裝
pip 安裝,不多說。
pip install pyotp
2.配對
配對就是移動設備和我們的 web 服務器配對。
首先,在服務器上使用如下代碼生成一次性密鑰:
>>> import pyotp
>>> pyotp.random_base32()
'BZ4TOJD4JWWJWPQBKP23FA55EMHA25Y2'
>>>
然后將這個密鑰以二維碼的形式讓手機(移動設備)掃描,掃描之后,手機上的應用就保存了這個密鑰。
3.驗證
接下來,在手機上就可以使用下面這段邏輯產生動態(tài)密碼了。
>>> totp = pyotp.TOTP('BZ4TOJD4JWWJWPQBKP23FA55EMHA25Y2')
>>> totp.now()
'941782'
>>>
現在,你有 30 秒的時間將這個 6 位數密碼提交到服務器(輸入到網頁上),服務器服務器也使用同樣的密鑰和當前時間戳,生成一個動態(tài)碼,跟用戶提交的動態(tài)碼比對。只要兩者不一致,就驗證失敗,也就是下面這段邏輯,如果超過 30 秒,(當然,30 秒可以自定義),也會失效:
>>> totp = pyotp.TOTP('BZ4TOJD4JWWJWPQBKP23FA55EMHA25Y2')
>>> totp.verify('941782')
True
>>> time.sleep(30)
>>> totp.verify('941782')
False
除了使用基于時間的動態(tài)密碼,也可以用基于計數的動態(tài)密碼,邏輯如下:
hotp = pyotp.HOTP('base32secret3232')
hotp.at(0) # => '260182'
hotp.at(1) # => '055283'
hotp.at(1401) # => '316439'
# OTP verified with a counter
hotp.verify('316439', 1401) # => True
hotp.verify('316439', 1402) # => False
4.那是不是手機上還有開發(fā)個 app ?
不用,我們直接使用現成的 Google Authenticator 就可以了。
如果你已安裝了 Google Authenticator,請點擊 ? 添加密鑰,然后掃描下發(fā)的二維碼,就可以生成動態(tài)碼:
然后你可以執(zhí)行下面這段代碼,就可以發(fā)現 pyotp 產生的動態(tài)碼和 Google Authenticator 產生的是一致的:
import pyotp
totp = pyotp.TOTP("JBSWY3DPEHPK3PXP")
print("Current OTP:", totp.now())
其實二維碼的信息就是 JBSWY3DPEHPK3PXP。
這樣,我們用 Google Authenticator 來產生動態(tài)密碼,網站上進行二次驗證,就可以實現 2FA 了。