OTP动态口令之Java实现双重认证

前言

双重认证(英语:Two-factor authentication,缩写为2FA),又译为双重验证、双因素认证、二元认证,又称两步骤验证(2-Step Verification,又译两步验证),是一种认证方法。

原理
动态密码的产生方式,主要是以时间差做为服务器与密代码生成器的同步条件。在需要登录的时候,就利用密代码生成器产生动态密码,OTP一般分为计次使用以及计时使用两种,计次使用的OTP产出后,可在不限时间内使用;计时使用的OTP则可设置密码有效时间,从30秒到两分钟不等,而OTP在进行认证之后即废弃不用,下次认证必须使用新的密码,增加了试图不经授权访问有限制资源的难度。

TOTP技术标准
https://datatracker.ietf.org/doc/html/rfc6238

相关技术文档

使用OTP动态口令(每分钟变一次)进行登录认证

利用Google API快速生成QR二维码


OTP扫描用字符串格式

格式:

otpauth://totp/账号?secret=秘钥

示例:

otpauth://totp/花伤情犹在?secret=RR7VFLUFFJPJ4FYFS66REZG6FROEI55M

可以手动输入账户和秘钥添加令牌

使用阿里云身份宝或者Google Authenticator时间同步实现OTP动态口令

在这里插入图片描述

或者将OTP字符串生成二维码

草料二维码生成器:https://cli.im/

在这里插入图片描述

手动输入账户和秘钥 或者 扫描二维码 即可添加令牌

在这里插入图片描述

利用Google API生成二维码

此项目就是利用Google API生成的二维码

链接参数详解:

  1. https://chart.googleapis.com/chart? 这是Google Chart API的头部,直接照抄就好了~
  2. &cht=qr 这是说图表类型为qr也就是二维码。
  3. &chs=200×200 这是说生成图片尺寸为200×200,是宽x高。这并不是生成图片的真实尺寸,应该是最大尺寸吧。
  4. &choe=UTF-8 这是说内容的编码格式为UTF-8,此值默认为UTF-8.其他的编码格式请参考Google API文档。
  5. &chld=L|4 L代表默认纠错水平; 4代表二维码边界空白大小,可自行调节。具体参数请参考Google API文档。
  6. &chl=XXXX 这是QR内容,也就是解码后看到的信息。包含中文时请使用UTF-8编码汉字,否则将出现问题。

j256开源两步验证

两步验证

<dependency>
    <groupId>com.j256.two-factor-auth</groupId>
    <artifactId>two-factor-auth</artifactId>
    <version>1.3</version>
</dependency>

Github地址

两步验证Java代码

两步身份验证 (2FA) Java 代码,它使用基于时间的一次性密码 (TOTP) 算法。您可以将此代码与 Google Authenticator 移动应用程序或 Authy 移动或浏览器应用程序一起使用。

生成秘钥

  1. 用于generateBase32Secret()为用户生成 base-32 格式的密钥。例如:“NY4A5CPJZ46LXZCP”
  2. 将密钥存储在与用户帐户关联的数据库中。
  3. 显示返回qrImageUrl(…)给用户的二维码图片URL。

用户使用图像将密钥加载到他的身份验证器应用程序中。

验证秘钥

  1. 用户将来自验证器应用程序的号码输入到 Web 服务器上的登录表单中。
  2. Web 服务器从数据库中读取与用户帐户关联的密钥。
  3. 服务器将用户输入与来自 的输出进行比较generateCurrentNumberString(…)。
  4. 如果它们相等,则允许用户登录。

代码示例

public static void main(String[] args) throws Exception {
    
    

        // 生成Base32秘钥
        String base32Secret = TimeBasedOneTimePasswordUtil.generateBase32Secret(32);

        System.out.println("secret = " + base32Secret);

        // 这是可以由验证程序显示的密钥的名称
        String keyId = "hsqyz";
        // 生成二维码
        System.out.println("Image url = " + TimeBasedOneTimePasswordUtil.qrImageUrl(keyId, base32Secret));
        //我们可以将此图像显示给用户,让他们将其加载到他们的身份验证程序中

        // 我们可以在这里使用代码并将其与用户输入进行比较
        String code = TimeBasedOneTimePasswordUtil.generateCurrentNumberString(base32Secret);

        System.out.println("code : "+code);

        /*
         * 此循环显示数字如何随时间变化
         */
        while (true) {
    
    
            long diff = TimeBasedOneTimePasswordUtil.DEFAULT_TIME_STEP_SECONDS
                    - ((System.currentTimeMillis() / 1000) % TimeBasedOneTimePasswordUtil.DEFAULT_TIME_STEP_SECONDS);
            code = TimeBasedOneTimePasswordUtil.generateCurrentNumberString(base32Secret);
            System.out.println("Secret code = " + code + ", change in " + diff + " seconds");
            Thread.sleep(1000);
        }


    }

suyin58开源两步验证

数据库表结构:

CREATE TABLE `t_user` (
  `username` varchar(30) COLLATE utf8_bin NOT NULL,
  `otp_sk` varchar(64) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

创建用户

  • 运行RegistTest的main方法,注意修改f_temp[临时二维码图片存放目录],email[接收二维码图片邮箱地址]
    工程部署在tomcat下,登录地址
  • http://127.0.0.1:8580/login.jsp

猜你喜欢

转载自blog.csdn.net/qq_31762741/article/details/122889805