GIT地址:https://github.com/suyin58/otp-demogit
動態碼截圖:github
在對外網開放的後臺管理系統中,使用靜態口令進行身份驗證可能會存在以下問題:算法
(1) 爲了便於記憶,用戶多選擇有特徵做爲密碼,全部靜態口令相比動態口令而言,容易被猜想和破解;數據庫
(2) 黑客能夠從網上或電話線上截獲靜態密碼,若是是非加密方式傳輸,用戶認證信息可被輕易獲取;安全
(3) 內部工做人員可經過合法受權取得用戶密碼而非法使用;服務器
靜態口令根本上不能肯定用戶的身份,其結果是,我的能夠輕鬆地僞造一個假身份或者盜用一個已有使用者的身份,給企業形成巨大的經濟和聲譽損失。本文主要介紹並實現了一種動態口令(OTP)的實現方式。dom
動態口令(OTP,One-Time Password)又稱一次性密碼,是使用密碼技術實現的在客戶端和服務器之間經過共享祕密的一種認證技術,是一種強認證技術,是加強目前靜態口令認證的一種很是方便技術手段,是一種重要的雙因素認證技術,動態口令認證技術包括客戶端用於生成口令產生器的,動態令牌,是一個硬件設備,和用於管理令牌及口令認證的後臺動態口令認證系統組成。工具
otp從技術來分有三種形式, 時間同步、事件同步、挑戰/應答。網站
(1) 時間同步阿里雲
原理是基於 動態令牌和 動態口令驗證服務器的時間比對,基於 時間同步的 令牌,通常每60秒產生一個新口令,要求服務器可以十分精確的保持正確的時鐘,同時對其令牌的晶振頻率有嚴格的要求,這種技術對應的終端是硬件令牌。
(2)事件同步
基於事件同步的令牌,其原理是經過某一特定的事件次序及相同的種子值做爲輸入,經過HASH算法中運算出一致的密碼。
(3)挑戰/應答
經常使用於的網上業務,在網站/應答上輸入 服務端下發的 挑戰碼, 動態令牌輸入該挑戰碼,經過內置的算法上生成一個6/8位的隨機數字,口令一次有效,這種技術目前應用最爲廣泛,包括刮刮卡、短信密碼、動態令牌也有挑戰/應答形式。
使用阿里雲身份寶(或者Google Authenticator)時間同步實現OTP動態口令
如上圖,是一種基於時間同步的OTP計算方式,是經過客戶端和服務器持有相同的密鑰並基於時間基數,服務端和客戶端採用相同的Hash算法,計算出長度爲六位的校驗碼。當客戶端和服務端計算出的校驗碼相同是,那麼驗證經過。
因爲客戶端須要存儲密鑰和計算校驗碼的載體,阿里雲的身份寶(或者Google 的Authenticator)提供了手機端的APP進行密鑰存儲和校驗碼計算。下面咱們以這兩款客戶端爲例,實如今應用採用OTP進行權限驗證,主要流程以下圖:
流程關鍵代碼以下,(更詳細代碼,請Git下載:https://github.com/suyin58/otp-demo)
1 用戶註冊:
1.1 生成OTP密鑰:
String secretBase32 = TotpUtil.getRandomSecretBase32(64);
oper.setOtpSk(secretBase32);
1.2 生成OTP掃描用字符串:
約定字符串格式以下:
String totpProtocalString = TotpUtil.generateTotpString(operCode, host, secretBase32);
1.3 將1.2中生成的字符串生成二維碼,經過郵件發送給用戶
String host = "otptest@wjs.com"; // 自定義 String totpProtocalString = TotpUtil.generateTotpString(operCode, host, secretBase32); String filePath = f_temp; String fileName = Long.toString(System.currentTimeMillis()) + ".png"; try{ QRUtil.generateMatrixPic(totpProtocalString, 150, 150, filePath, fileName); }catch (Exception e){ throw new RuntimeException("生成二維碼圖片失敗:" + e.getMessage()); } String content = "用戶名:"+operCode+"</br>" +"系統使用密碼 + 動態口令雙因素認證的方式登陸。</br>請按如下方式激活手機動態口令:</br>安卓用戶請點擊<a href='http://otp.aliyun.com/updates/shenfenbao.apk'>下載</a>," +"</br>蘋果手機在AppStore中搜索【身份寶】(Alibaba)。下載安裝後,經過掃描如下二維碼激活動態口令。</br>" +"<img src=\"cid:image\">"; EmailBaseLogic emailBaseLogic = new EmailBaseLogic(); // String to, String title, String content, String imagePath emailBaseLogic.sendWithPic(email,"帳戶開立通知", content, filePath + "/" + fileName);
1.4 將用戶註冊信息與1.1的OTP密鑰存儲到數據庫中
數據存儲代碼(略)
2 客戶端工具使用
2.1 下載APP
安卓用戶下載地址:http://otp.aliyun.com/updates/shenfenbao.apk
蘋果手機在AppStore中搜索【身份寶】(Alibaba),或者Google Authenticator
2.2 掃描二維碼
使用下載的APP,掃描1.3郵件中的二維碼,客戶端獲取密鑰。APP使用密鑰基於時間算出6位校驗碼(每分鐘變化)。
1 用戶登陸
客戶端輸入登陸用戶名、用戶密碼,以及2.2客戶端工具中的6位校驗碼。
1.1 服務端根據用戶名和用戶密碼獲取用戶信息和密鑰
代碼參考略
1.2 服務端使用密鑰基於時間算出6位校驗碼
String secretHex = ""; try { secretHex = HexEncoding.encode(Base32String.decode(secretBase32)); } catch (Base32String.DecodingException e) { LOGGER.error("解碼" + secretBase32 + "出錯,", e); throw new RuntimeException("解碼Base32出錯"); } long X = 30; String steps = "0"; DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); df.setTimeZone(TimeZone.getTimeZone("UTC")); long currentTime = System.currentTimeMillis() / 1000L; try { long t = currentTime / X; steps = Long.toHexString(t).toUpperCase(); while (steps.length() < 16) steps = "0" + steps; return generateTOTP(secretHex, steps, "6", "HmacSHA1"); } catch (final Exception e) { LOGGER.error("生成動態口令出錯:" + secretBase32, e); throw new RuntimeException("生成動態口令出錯"); }
1.3 比較客戶端和客戶端校驗碼是否一致
代碼參考略
其餘,Demo中的例子可使用身份 + 密碼,先進行密碼驗證,在經過動態口令進行二次驗證,使系統登陸更加安全可靠。