google验证码即校验
package com.okni.okpool.okfinance.util; import com.okni.okpool.okfinance.config.TOTP; import org.apache.commons.codec.binary.Base32; import org.apache.commons.codec.binary.Hex; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.security.SecureRandom; /** * GoogleAuthenticator 工具类 */ public class GoogleAuthenticatorUtils { /** * 时间前后偏移量 * 用于防止客户端时间不精确导致生成的TOTP与服务器端的TOTP一直不一致 * 如果为0,当前时间为 10:10:15 * 则表明在 10:10:00-10:10:30 之间生成的TOTP 能校验通过 * 如果为1,则表明在 * 10:09:30-10:10:00 * 10:10:00-10:10:30 * 10:10:30-10:11:00 之间生成的TOTP 能校验通过 * 以此类推 */ private static final int timeExcursion = 1; /** * 创建一个密钥 */ 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.toLowerCase(); } /** * 校验方法 * * @param secretKey 密钥 * @param code 用户输入的TOTP */ public static boolean verify(String secretKey, String code) { long time = System.currentTimeMillis() / 1000 / 30; for (int i = -timeExcursion; i <= timeExcursion; i++) { String totp = getTOTP(secretKey, time + i); if (code.equals(totp)) { return true; } } return false; } /** * 根据密钥获取验证码 * 返回字符串是因为数值有可能以0开头 * @param secretKey 密钥 * @param time 第几个30秒 System.currentTimeMillis() / 1000 / 30 */ public static String getTOTP(String secretKey, long time) { Base32 base32 = new Base32(); byte[] bytes = base32.decode(secretKey.toUpperCase()); String hexKey = Hex.encodeHexString(bytes); String hexTime = Long.toHexString(time); return TOTP.generateTOTP(hexKey, hexTime, "6"); } /** * 生成Google Authenticator二维码所需信息 * Google Authenticator 约定的二维码信息格式 : otpauth://totp/{issuer}:{account}?secret={secret}&issuer={issuer} * 参数需要url编码 +号需要替换成%20 * @param secret 密钥 使用createSecretKey方法生成 * @param account 用户账户 如: example@domain.com 138XXXXXXXX * @param issuer 服务名称 如: Google Github 印象笔记 */ public static String createGoogleAuthQRCodeData(String secret, String account, String issuer) { String qrCodeData = "otpauth://totp/%s?secret=%s&issuer=%s"; try { return String.format(qrCodeData, 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 ""; } }