你們應該對兩步驗證都熟悉吧?如蘋果有自帶的兩步驗證策略,防止用戶帳號密碼被盜而鎖定手機進行敲詐,這種例子家常便飯,因此蘋果都建議你們開啓兩步驗證的。java
Google 的身份驗證器通常也是用於登陸進行兩步驗證,和蘋果的兩步驗證是一樣的道理。只不過 Google 的身份驗證器用得更多更普遍,如 GitHub 的兩步驗證都是基於 Google 身份驗證器。算法
Google Authenticator 身份驗證器是一款基於時間與哈希的一次性密碼算法的兩步驗證軟件令牌,用戶須要下載手機 APP(Authenticator),該手機 APP 與網站進行綁定,當網站驗證完用戶名和密碼以後會驗證此 APP 上對應生成的 6 位驗證碼數字,驗證經過則成功登陸,不然登陸失敗。安全
咱們來看下 Github 上的使用 Google 身份驗證器開啓兩步驗證的應用。微信
如圖所示,默認 Github 是沒有開啓兩步驗證的,點擊設置按鈕進行設置。工具
Github 提供了基於 APP (谷歌身份驗證器)和短信驗證碼兩種兩步驗證的方式,咱們選擇第一種谷歌身份驗證器。post
進入第一種驗證模式,接下來展現了一堆的恢復碼,用來當 APP 驗證器不能工做的緊急狀況使用。把它們保存起來,而後點擊下一步。網站
這個就是身份驗證器的關鍵了,下載 Google 的 Authenticator
APP,而後掃描這個二維碼進行綁定。google
綁定以後,APP Github 模塊下面會顯示一個 6 位的驗證碼,把它輸入到上面那個框裏面就好了。編碼
以下圖所示,已經成功開啓兩步驗證了。加密
接下來咱們退出 Github 再從新登陸,頁面就會提示要輸入 Google 的身份驗證器驗證碼了,若是 APP 不能正常工做,最下方還能經過以前保存下來的恢復碼進行登陸。
好了,Google Authenticator 使用就到這裏,那它是如何工做的,它是什麼原理呢?咱們的網站、APP 如何接入 Google Authenticator,接下來咱們一一拉開謎底。
實際上 Google Authenticator 採用的是 TOTP 算法(Time-Based One-Time Password,即基於時間的一次性密碼),其核心內容包括如下三點。
一、安全密鑰
是客戶端和服務端約定的安全密鑰,也是手機端 APP 身份驗證器綁定(手機端經過掃描或者手輸安全密鑰進行綁定)和驗證碼的驗證都須要的一個惟一的安全密鑰,該密鑰由加密算法生成,並最後由 Base32 編碼而成。
二、驗證時間
Google 選擇了 30 秒做爲時間片,T的數值爲 從Unix epoch(1970年1月1日 00:00:00)來經歷的 30 秒的個數,因此在 Google Authenticator 中咱們能夠看見驗證碼每一個 30 秒就會刷新一次。
更詳細原理參考:
https://blog.seetee.me/post/2...
三、簽署算法
Google 使用的是 HMAC-SHA1 算法,全稱是:Hash-based message authentication code(哈希運算消息認證碼),它是以一個密鑰和一個消息爲輸入,生成一個消息摘要做爲輸出,這裏以 SHA1 算法做爲消息輸入。
使用 HMAC 算法是由於只有用戶自己知道正確的輸入密鑰,所以會獲得惟一的輸出,其算法能夠簡單表示爲:
hmac = SHA1(secret + SHA1(secret + input))
事實上,TOTP 是 HMAC-OTP(基於HMAC的一次密碼生成)的超集,區別是 TOTP 是以當前時間做爲輸入,而HMAC-OTP 則是以自增計算器做爲輸入,該計數器使用時須要進行同步。
知道上面的原理,咱們就能夠來應用實戰了。
/** * 微信公衆號:Java技術棧 */ public class AuthTest { @Test public void genSecretTest() { String secret = GoogleAuthenticator.generateSecretKey(); String qrcode = GoogleAuthenticator.getQRBarcodeURL("Java技術棧", "javastack.cn", secret); System.out.println("二維碼地址:" + qrcode); System.out.println("密鑰:" + secret); } @Test public void verifyTest() { String secret = "ZJTAQGLVOZ7ATWH2"; long code = 956235; GoogleAuthenticator ga = new GoogleAuthenticator(); boolean r = ga.verifCode(secret, code); System.out.println("是否正確:" + r); } }
第一個方法是生成密鑰和一個掃描二維碼綁定的URL。
第二個方法是根據密鑰和驗證碼進行驗證。
這裏僅提供一下 GoogleAuthenticator 類的源碼邏輯參考。
http://awtqty-zhang.iteye.com...
若是有收穫歡迎點贊轉發,也能夠留言發表你的疑問和見解。
教程:史上最強 Spring Boot & Cloud 教程彙總