200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 双因子认证 TOTP动态口令认证

双因子认证 TOTP动态口令认证

时间:2020-09-03 00:05:41

相关推荐

双因子认证 TOTP动态口令认证

介绍

TOTP:Time-based One-Time Password写,基于对称密钥与时间戳算法的一次性认证码。 时间同步,基于客户端的动态口令和动态口令验证服务器的时间比对,默认每30秒产生一个新口令,要求客户端和服务器能够十分精确的保持正确的时钟,客户端和服务端基于时间计算的动态口令才能一致。

算法安全的核心在于密钥 , 每个人通过对应账户生成的密钥是不同的 . 当他们用同一个算法加密时 , 会生成不同的随机密码,认证时客户端需要使用阿里身份宝,Goole 身份验证器等工具生成认证码。

totp认证java代码实现

public class OptUtil {private OptUtil() {}/** 生成32位的otp密钥 */@SneakyThrowspublic static String generateSecretKey() {SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");sr.setSeed(Base64.decodeBase64("b5rpa6kcdux2fpq0tkrt2wwsqeqmho0d"));byte[] buffer = sr.generateSeed(20);Base32 codec = new Base32();return codec.encodeToString(buffer);}/** 校验 opt code */public static boolean checkCode(String secret, int code) {Base32 codec = new Base32();byte[] decodedKey = codec.decode(secret);long nowInSeconds = System.currentTimeMillis() / 1000L;//考虑到网络延迟,预留1秒钟容错for (int i = 0; i < 2; i++) {long time = (nowInSeconds - i) / 30L;int hash = verifyCode(decodedKey, time);if (hash == code) {return true;}}//Opt校验不通过return false;}@SneakyThrowsprivate static int verifyCode(byte[] key, long t) {byte[] data = new byte[8];long value = t;for (int i = 8; i-- > 0; value >>>= 8) {data[i] = (byte) value;}final String algorithm = "HmacSHA1";SecretKeySpec signKey = new SecretKeySpec(key, algorithm);Mac mac = Mac.getInstance(algorithm);mac.init(signKey);byte[] hash = mac.doFinal(data);int offset = hash[20 - 1] & 0xF;long truncatedHash = 0;for (int i = 0; i < 4; ++i) {truncatedHash <<= 8;truncatedHash |= (hash[offset + i] & 0xFF);}truncatedHash &= 0x7FFFFFFF;truncatedHash %= 1000000;return (int) truncatedHash;}}

生成totp密钥绑定二维码

添加依赖

<!--二维码生成--><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.3</version></dependency>

二维码生成代码

/*** @description 生成二维码工具*/public class QrCodeUtil {private QrCodeUtil() {}/*** @description: 生成一个普通的黑白二维码* @param content 二维码内容* @param width 生成图片矿都* @param height 生成图片高度* @return 二维码图片字节流**/public static byte[] drawQrCode(String content, int width, int height) throws WriterException, IOException {MultiFormatWriter multiFormatWriter = new MultiFormatWriter();BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, width, height, new HashMap<>() {private static final long serialVersionUID = 1L;{put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);put(EncodeHintType.CHARACTER_SET, "UTF-8");put(EncodeHintType.MARGIN, 0);}});BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 开始利用二维码数据图片,分别设为黑(0xFFFFFFFF)白(0xFF000000)两色for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);}}image.flush();//分配13KbByteArrayOutputStream outputStream = new ByteArrayOutputStream(13312);ImageIO.write(image, "png", outputStream);return outputStream.toByteArray();}}

新增接口生成base64绑定二维码图片数据

/** 生成密钥绑定二维码 */@GetMapping(path = "/img/zx")@SneakyThrowspublic String keyZxImg(){String key = OptUtil.generateSecretKey();final String QRCODE_TEMPLATE = "otpauth://totp/xxx:{0}?secret={1}&issuer={2}";String content = MessageFormat.format(QRCODE_TEMPLATE, "user@app", key, "DAS_TOTP");byte[] contents = QrCodeUtil.drawQrCode(content, 320, 320);return Base64.getEncoder().encodeToString(contents);}

客户端使用类似阿里身份宝等工具扫描“密钥绑定二维码”接口生成的base64编码图片即可绑定密钥

totp认证码校验

/** 使用opt验证码登录 */@GetMapping(path = "/check")public boolean login(@RequestParam int optCode){return OptUtil.checkCode(key_cache, optCode);}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。