首页 > 其他分享 >接入Google认证Google Authenticator

接入Google认证Google Authenticator

时间:2023-09-14 23:22:41浏览次数:35  
标签:Google 随机码 32 验证码 认证 Authenticator API import

  • 介绍

既然来看该文章就应该知道Google的两步认证是干什么的,如果需要APP(Google Authenticator)的可以私信我。

验证原理讲解:

为每个用户在注册之前生成32位随机码(该码一般会存入数据库)。

调用API传入32位随机码,生成正确的6位验证码,每隔1分种会变化。

根据用户输入的6位验证码和正确的6位验证码做匹配,相同则登陆成功,不同则验证码时间失效或错误。

用户绑定讲解:

调用API生成32位随机码。。

调用API生成二维码QR字符串,需要传入用户信息(比如邮箱,昵称等),标题,以及生成的32位随机码。

调用API将二维码QR字符串转化为图片后以Base64的方式展现到前端页面上。

用户使用APP(Google Authenticator)扫码添加后,点击确认绑定,即可看到6位验证码。

后端根据API生成的32位随机码,用户信息(用来确定数据库中用户记录),以及输入6位验证码,通过API传入32位随机码验证,当其与输入的验证码相同时,则绑定成功,把32位随机码持久化与用户绑定。

  • 准备工作

导入一下Maven依赖

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.10</version>
        </dependency>

  

  • 导入工具类GoogleAuthenticatorUtils
import org.apache.commons.codec.binary.Base32;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

/**
 * @ProjectName: cdkj-framework
 * @Package: com.cdkjframework.util.tool
 * @ClassName: GoogleAuthenticatorUtils
 * @Description: 身份验证
 * @Author: xiaLin
 * @Date: 2023/4/3 15:16
 * @Version: 1.0
 */
public class GoogleAuthenticatorUtils {

  /**
   * 生成的key长度( Generate secret key length)
   */
  public static final int SECRET_SIZE = 10;

  /**
   * SEED 值
   */
  public static final String SEED = "g8GjEvTbW5oVSV7avL47357438reyhreyuryetredLDVKs2m0QN7vxRs2im5MDaNCWGmcD2rvcZx";

  /**
   * Java实现随机数算法
   */
  public static final String RANDOM_NUMBER_ALGORITHM = "SHA1PRNG";

  /**
   * 最多可偏移的时间
   * // default 3 - max 17
   */
  private int window_size = 3;

  /**
   * 设置窗口大小。这是一个整数值,表示
   * 我们允许30秒的窗口窗口越大
   * 时钟歪斜。
   *
   * @param s window size - must be >=1 and <=17. Other values are ignored
   */
  public void setWindowSize(int s) {
    if (s >= 1 && s <= 17)
      window_size = s;
  }

  /**
   * 生成一个随机密钥。这必须由服务器保存,并且
   * 与用户帐户关联,以验证谷歌显示的代码
   * 身份验证人。用户必须在其设备上注册此机密。
   * 生成一个随机秘钥
   *
   * @return 返回 secret key
   */
  public static String generateSecretKey() {
    SecureRandom random = null;
    try {
      random = SecureRandom.getInstance(RANDOM_NUMBER_ALGORITHM);
      random.setSeed(Base64.decodeBase64(SEED));
      byte[] buffer = random.generateSeed(SECRET_SIZE);
      Base32 codec = new Base32();
      byte[] bEncodedKey = codec.encode(buffer);
      String encodedKey = new String(bEncodedKey);
      return encodedKey;
    } catch (NoSuchAlgorithmException e) {
      // 不应该发生。。。配置错误
    }
    return null;
  }

  /**
   * 生成一个google身份验证器,识别的字符串,只需要把该方法返回值生成二维码扫描就可以了。
   *
   * @param user   账号
   * @param secret 密钥
   * @return 返回结果
   */
  public static String getQRBarcode(String user, String secret, String issuer) {
    String format = "otpauth://totp/%s?secret=%s&issuer=%s";
    return String.format(format, user, secret, issuer);
  }

  /**
   * 验证code是否合法
   *
   * @param secret   用户的秘密
   * @param code     用户设备上显示的代码
   * @param timeMsec 时间(毫秒)
   * @return 返回结果
   */
  public boolean checkCode(String secret, long code, long timeMsec) {
    Base32 codec = new Base32();
    byte[] decodedKey = codec.decode(secret);
    // 将unix毫秒时间转换为30秒的“窗口”
    // 这是根据TOTP规范(有关详细信息,请参阅RFC)
    long t = (timeMsec / 1000L) / 30L;
    // 窗口用于检查最近生成的代码。
    // 您可以使用此值来调整您愿意走多远。
    for (int i = -window_size; i <= window_size; ++i) {
      long hash;
      try {
        hash = verifyCode(decodedKey, t + i);
      } catch (Exception e) {
        // 抛出的异常将是罕见的,并且是静态的
        // 配置问题
        throw new RuntimeException(e.getMessage());
      }
      if (hash == code) {
        return true;
      }
    }
    // 验证代码无效。
    return false;
  }

  /**
   * 验证随机码
   *
   * @param key 值
   * @param t   时间
   * @return 返回结果
   * @throws NoSuchAlgorithmException
   * @throws InvalidKeyException
   */
  private static int verifyCode(byte[] key, long t) throws NoSuchAlgorithmException, InvalidKeyException {
    byte[] data = new byte[8];
    long value = t;
    for (int i = 8; i-- > 0; value >>>= 8) {
      data[i] = (byte) value;
    }
    SecretKeySpec signKey = new SecretKeySpec(key, "HmacSHA1");
    Mac mac = Mac.getInstance("HmacSHA1");
    mac.init(signKey);
    byte[] hash = mac.doFinal(data);
    int offset = hash[20 - 1] & 0xF;
    // 我们使用long是因为Java没有无符号int。
    long truncatedHash = 0;
    for (int i = 0; i < 4; ++i) {
      truncatedHash <<= 8;
      // 我们正在处理签名字节: 我们只保留第一个字节。
      truncatedHash |= (hash[offset + i] & 0xFF);
    }
    truncatedHash &= 0x7FFFFFFF;
    truncatedHash %= 1000000;
    return (int) truncatedHash;
  }
}

  

  • 需要注意

该方式生成的码由于偏移量的问题可能出现验证码过期却依然能通过验证的情况,可根据情况调整便宜量;具体生成二维码、验证接口这里不在贴代码了自行实现。

标签:Google,随机码,32,验证码,认证,Authenticator,API,import
From: https://www.cnblogs.com/cdkj/p/17703804.html

相关文章

  • uniapp-net core后台-实现认证
    一在program.cs中添加cookie认证builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options=>{options.Cookie.Name="auth";options.ExpireTimeSpan=TimeSpan.FromDays(1);options.Sli......
  • 儿童坐便器亚马逊爆品需要做的检测认证?CPC认证
    儿童座便器,是为儿童量身定制的。最初为了培养宝宝自己坐便的习惯,座便器会设计的很人性化。适宜儿童心理和生理。比如坐便器的内圈大小,适合宝宝小屁屁。座便器一改成人马桶的死气沉沉,有一些小动物图案,吸引宝宝去完成坐,并逐渐养成习惯,那么和将来宝宝上幼儿园就接轨了。但是生产就离......
  • 部署openldap服务并配置jumpsever、jira、mindoc、gitlab、jenkins集成ldap认证
    背景公司各种信息化系统越来越多,需要记住的用户账号也越来越多,人员入职离职就要分别在不同的各种系统上进行添加和删除比较繁锁,急需要一个可以统一认证的服务,于是就开始研究ldap,ldap中openldap是开源的方便使用,于是花了大概2个月时间才把标题上面的这几个服务全部调通,以下记录配置......
  • 2023年9月传统行业NPDP产品经理国际认证报名就到这
    产品经理国际资格认证NPDP是新产品开发方面的认证,集理论、方法与实践为一体的全方位的知识体系,为公司组织层级进行规划、决策、执行提供良好的方法体系支撑。  【认证机构】 产品开发与管理协会(PDMA)成立于1979年,是全球范围内产品开发与管理专业人士最杰出的倡导者,协助个人、企业......
  • 2023年9月CSPM-3国标项目管理中级认证报名到这就对了
    CSPM-3中级项目管理专业人员评价,是中国标准化协会(全国项目管理标准化技术委员会秘书处),面向社会开展项目管理专业人员能力的等级证书。旨在构建多层次从业人员培养培训体系,建立健全人才职业能力评价和激励机制的要求,培养我国项目管理领域复合型人才。  【证书含金量】 ·竞聘优先......
  • 2023年9月DAMA-CDGA/CDGP数据治理认证报名到这就对了
    DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业发展里程碑及发展阶梯定义,帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力,促进开展工作实践应用及实际问题解决,形成企业所需的新数字经济下的核心职业竞争能力。DAMA是数据管理方面的认证,帮助数据从业者提升......
  • CPSC新一轮严抓,不符合CPSC要求,卖家多个店铺受牵连,CPC认证主要标准和规范
    货物不幸被CPSC扣查如何处理?查验的方式有:1.CPSC部门安排人员到海外仓进行查验。2.海外仓寄样品给到CPSC部门检测。在查验结果未出之前,该批产品都不能发走。如果卖家的货物不幸被CPSC扣查,应该如何应对呢?好在,有热心卖家就这一点做了经验分享:1、提供证据以支持该产品的合规性卖家可在......
  • public ::google::protobuf::Message
     public::google::protobuf::Messagefilelist继承..... .protomessageabc{requiredstringaa=1;optionalstringbb=4; }messageDeparts{repeatedabccc=1;......
  • 上架亚马逊儿童折叠式和非折叠式椅子和凳子的检测认证?CPC认证
    本政策适用的儿童折叠式和非折叠式椅子和凳子儿童折叠式和非折叠式椅子和凳子是带有刚性框架的座椅家具,用于支撑儿童的身体,使其能够以直立或倾斜的姿势坐立或休息。本政策适用的折叠椅和折叠凳的座部高度不超过15英寸,可能带或不带摇摆底座,儿童可在无人帮助的情况下坐上去或下来。......
  • 19C RAC更换OCR磁盘组后,ASM密码认证导致集群CRSD服务无法启动
    前言一套19.19的RAC,OCR所在的ASM磁盘组从+GRID更换为+DG_GRID,然后强制删除了原来的+GRID磁盘组,最终导致该集群无法启动。 过程1、启动过程中,CSS服务正常启动,但CRS服务无法启动。此时,节点2的alertasm2.log日志中提示如下错误。2023-06-23T17:44:33.667188+08:00Errorsi......