目前的客户端App:
- Google Authenticator
- 阿里的《身份宝》 (兼容Google 身份验证器)
操作过程
绑定证书或密钥
- 服务器随机生成密钥,类似“DPI45HKISEXU6HG7” ,并把密钥和用户登录账号一起存入数据库
- 在页面上显示一个二维码,内容是一个URI地址,格式:otpauth://totp/账号?secret=密钥
- 使用客户端扫描二维码,把密钥保存在客户端
用户登录认证
- 客户端每30秒会使用密钥加(时间戳/30)通过一种算法,生成一个6位数字的一次性密码
- 用户登录的时候输入一次性密码
- 服务器端使用保存在数据库中的密钥“DPI45HKISEXU6HG7”和(时间戳/30)通过同一种算法生成一个6位数字的一次性密码,如果6位数字密码和用户输入的相等,那么服务器验证通过。
测试代码
- maven依赖
<dependency>
<groupId>com.warrenstrange</groupId>
<artifactId>googleauth</artifactId>
<version>1.2.0</version>
</dependency>
- 随机生成密钥字符串
public static String createSecretKey(){
SecureRandom random = new SecureRandom();
byte[] bytes = new byte[20];
random.nextBytes(bytes);
Base32 base32 = new Base32();
String secretKey = base32.encodeToString(bytes);
return secretKey.toUpperCase();
}
- 拼接二维码URI
public static String createGoogleAuthQR(String secret,String account,String issuer){
String qrCode = "otpauth://totp/%s?secret=%s&issuer=%s";
try {
return String.format(qrCode, URLEncoder.encode(issuer+":"+account,"UTF-8").replace("+", "%20"),
URLEncoder.encode(secret,"UTF-8").replace("+", "%20"),
URLEncoder.encode(issuer, "UTF-8").replace("+", "%20"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return "";
}
- 使用依赖包解析密钥串获取数字验证码
public static Integer getTOTP(String secretKey){
GoogleAuthenticator googleAuthenticator = new GoogleAuthenticator();
int pass = googleAuthenticator.getTotpPassword(secretKey);
return pass;
}