diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/digest/otp/TOTP.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/digest/otp/TOTP.java index 315b7221d..c5387788c 100644 --- a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/digest/otp/TOTP.java +++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/digest/otp/TOTP.java @@ -26,7 +26,34 @@ import java.time.Instant; * 要求客户端和服务器能够十分精确的保持正确的时钟,客户端和服务端基于时间计算的动态口令才能一致。

* *

参考:https://github.com/jchambers/java-otp

+ * OTP基于具有时间戳计数器的OTP。 + * 通过定义纪元(T0)的开始并以时间间隔(TI)为单位计数,将当前时间戳变为整数时间计数器(TC)。 例如: * + * TC = floor, + * TOTP = HOTP(SecretKey,TC), + * TOTP-Value = TOTP mod 10d,其中d是一次性密码的所需位数。 + * 像google auth的二步认证使用了这种方式。 + * + * 认证过程 + * 生成二维码,带有otpauth链接的google地址 + * 生成公用密钥 + * 返回给app,同时用户户和服务名也会返回,这时密钥是被base32加密过的,app存储,以后用这个密钥来生成6位校验码 + * 服务端同时存储这个密钥和用户名,你可以把用户名当key,把密钥当value进行存储 + * app每30秒生成一个6位校验码,用户使用这个码来网站进行登陆 + * 服务器使用存储的密钥+fmac算法生成6位随机数,与客户端传来的数进行对比 + * 两个码相等,授权成功,反之,失败.(注意,服务端可以根据当前登陆的用户名拿到它的密钥,有了密钥,再进行totp的算法生成校验码) + * + * + * 登陆的过程整理 + * 用户和密码先登陆 + * session里存储了用户名等信息 + * 产生二维码及密钥,密钥存储到服务器的k/v介质里,k使用session里的用户名,v使用刚才的密钥 + * 客户使用app扫二维码,产生新的6位数字 + * 客户在用户名和密码登陆后,进行验证码页面,输入刚才的6位数字 + * 提交到服务端,服务端根据用户名取出对应的密钥,然后使用totp算法生成6位数字 + * 如果服务端与客户端数字相同,表示登陆成功! + * + * * @author Looly */ public class TOTP extends HOTP {