谷歌验证

1,338 阅读2分钟

引言:更多相关请看 Java其它
引入依赖:

<dependency>
            <groupId>de.taimos</groupId>
            <artifactId>totp</artifactId>
            <version>1.0</version>
        </dependency>

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

        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.2.1</version>
        </dependency>

代码如下:

import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import de.taimos.totp.TOTP;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base32;
import org.apache.commons.codec.binary.Hex;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.util.Scanner;

/**
 * 谷歌验证
 */
@Slf4j
public class GoogleAuthUtil {

    /**
     * 谷歌验证每30秒生成一个唯一的验证码,
     * 需要
     * @param args
     */
    public static void main(String[] args) {
//        String s1 = generateSecretKey();
        String s2 = "NAXLNPSOQER27H7AFJRXLLBVEP23MXL7";
        String s = "V2EXFANTGICYYNWUGOHLYNTNDM7D4UUP";
        String totpCode = getTOTPCode(s);
        System.out.println(totpCode);
        String secretKey = "V2EXFANTGICYYNWUGOHLYNTNDM7D4UUP";
        String lastCode = null;
        boolean b = checkCode(s, "556347");
        System.out.println(b);
        System.out.println(checkCode(s2, "909953"));
    }

    /**
     * -生成QR码。让我们使用ZXing库
     * @param barCodeData
     * @param filePath 文件目录
     * @param height 高
     * @param width 宽
     * @throws WriterException
     * @throws IOException
     */
    public static void createQRCode(String barCodeData, String filePath, int height, int width){

        try (FileOutputStream out = new FileOutputStream(filePath)) {
            BitMatrix matrix = new MultiFormatWriter().encode(barCodeData, BarcodeFormat.QR_CODE,
                    width, height);
            MatrixToImageWriter.writeToStream(matrix, "png", out);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 需要从Google接收条形码数据。它需要某种特殊格式,因此这是我们生成此数据的方法。
     *
     * @param secretKey  秘密密钥
     * @param account 帐户是系统中的用户ID。通常是用户的电子邮件或用户名。它用于标记Google Authenticator中的条目。
     * @param issuer 发行者是公司或组织的名称,也用于标记目的。
     * @return
     */
    public static String getGoogleAuthenticatorBarCode(String secretKey, String account, String issuer) {
        try {
            return "otpauth://totp/"
                    + URLEncoder.encode(issuer + ":" + account, "UTF-8").replace("+", "%20")
                    + "?secret=" + URLEncoder.encode(secretKey, "UTF-8").replace("+", "%20")
                    + "&issuer=" + URLEncoder.encode(issuer, "UTF-8").replace("+", "%20");
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException(e);
        }
    }

    /**
     * 检查6位码是否正常
     *
     * @param secretKey 秘钥
     * @param code 六位码
     * @return
     */
    public static boolean checkCode(String secretKey, String code) {
        String totpCode = getTOTPCode(secretKey);
        System.out.println("目前的生成的六位码:" + totpCode);
        if (totpCode != null && totpCode != "" && code != null && code != "" && totpCode.equals(code)) {
            return true;
        }
        return false;
    }

    /**
     * base32编码的秘密密钥转换为十六进制并使用TOTP根据当前时间将其转换为6位代码
     *
     * @param secretKey
     * @return
     */
    public static String getTOTPCode(String secretKey) {
        Base32 base32 = new Base32();
        byte[] bytes = base32.decode(secretKey);
        String hexKey = Hex.encodeHexString(bytes);
        return TOTP.getOTP(hexKey);
    }

    /**
     * Google身份验证器需要20个字节的密钥,编码为base32字符串。我们需要使用以下代码生成此密钥
     *
     * @return
     */
    public static String generateSecretKey() {
        SecureRandom random = new SecureRandom();
        byte[] bytes = new byte[20];
        random.nextBytes(bytes);
        Base32 base32 = new Base32();
        return base32.encodeToString(bytes);
    }
}