当前位置: 首页 > news >正文

GoogleCodeUtil.java

Google动态验证码实现  GoogleCodeUtil.java

package zwf;import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;/**
https://mvnrepository.com/artifact/commons-codec/commons-codec/1.18.0<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.18.0</version>
</dependency>*/
import org.apache.commons.codec.binary.Base32;/**
https://mvnrepository.com/artifact/com.warrenstrange/googleauth/1.5.0<!-- https://mvnrepository.com/artifact/com.warrenstrange/googleauth -->
<dependency><groupId>com.warrenstrange</groupId><artifactId>googleauth</artifactId><version>1.5.0</version>
</dependency>*/
import com.warrenstrange.googleauth.GoogleAuthenticator;
import com.warrenstrange.googleauth.GoogleAuthenticatorConfig;
import com.warrenstrange.googleauth.GoogleAuthenticatorKey;
import com.warrenstrange.googleauth.GoogleAuthenticatorQRGenerator;/**
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/client/utils/URIBuilderat com.warrenstrange.googleauth.GoogleAuthenticatorQRGenerator.getOtpAuthTotpURL(GoogleAuthenticatorQRGenerator.java:168)at com.warrenstrange.googleauth.GoogleAuthenticatorQRGenerator.getOtpAuthURL(GoogleAuthenticatorQRGenerator.java:143)at zwf.GoogleAuthenticatorUtil.generateQRUrl(GoogleAuthenticatorUtil.java:92)at zwf.GoogleAuthenticatorUtil.main(GoogleAuthenticatorUtil.java:163)
Caused by: java.lang.ClassNotFoundException: org.apache.http.client.utils.URIBuilderat java.net.URLClassLoader.findClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)... 4 morehttps://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient/4.5.13<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>*//**
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/message/ParserCursorat org.apache.http.client.utils.URLEncodedUtils.splitSegments(URLEncodedUtils.java:320)at org.apache.http.client.utils.URLEncodedUtils.splitPathSegments(URLEncodedUtils.java:348)at org.apache.http.client.utils.URIBuilder.setPath(URIBuilder.java:293)at com.warrenstrange.googleauth.GoogleAuthenticatorQRGenerator.getOtpAuthTotpURL(GoogleAuthenticatorQRGenerator.java:171)at com.warrenstrange.googleauth.GoogleAuthenticatorQRGenerator.getOtpAuthURL(GoogleAuthenticatorQRGenerator.java:143)at zwf.GoogleAuthenticatorUtil.generateQRUrl(GoogleAuthenticatorUtil.java:108)at zwf.GoogleAuthenticatorUtil.main(GoogleAuthenticatorUtil.java:179)
Caused by: java.lang.ClassNotFoundException: org.apache.http.message.ParserCursorat java.net.URLClassLoader.findClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)... 7 morehttps://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore/4.4.15
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><version>4.4.15</version>
</dependency>*//*** Google动态验证码实现* * https://www.lzltool.com/GoogleDynamicPassword* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com*/
public class GoogleCodeUtil
{/*** 动态密码的有效期,默认30秒, 30 * 1000 = 10秒* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @return*/private static final long TIME_STEP_SIZE_IN_MILLIS = 30 * 1000;/*** 允许的时间窗口时间步长,默认1* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @return*/private static final int WINDOW_SIZE = 1;/*** 生成一个随机的 Base32 编码的密钥* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @return 生成的 Base32 编码的密钥*/public static String generateSecretKey(){// 创建一个安全的随机数生成器SecureRandom random = new SecureRandom();// 生成一个长度为 20 的字节数组byte[] bytes = new byte[20];// 用随机数填充字节数组random.nextBytes(bytes);// 创建一个 Base32 编码器Base32 base32 = new Base32();// 将字节数组编码为 Base32 字符串并返回return base32.encodeToString(bytes);}/*** 根据密钥生成一个可供 Google Authenticator 扫描的二维码链接* * https://api.qrserver.com/v1/create-qr-code/?data=otpauth://totp/YourAppName:user@example.com?secret=YOUR_SECRET_KEY&issuer=YourAppName* * url转义* :     %3A* //    %2F%2F* @     %40* ?     %3F* =     %3D* &     %26* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @param secretKey            用于生成二维码链接的密钥* @param appName              应用程序的名称* @param email                用户的邮箱地址* @param timeStepSizeInMillis 动态密码的时间步长(毫秒)* @param windowSize           允许的时间窗口时间步长* @return 生成的二维码链接*/public static String generateQRUrl(String secretKey, String appName, String email, long timeStepSizeInMillis,int windowSize){// 构建 GoogleAuthenticator 的配置对象,设置时间步长GoogleAuthenticatorConfig config = new GoogleAuthenticatorConfig.GoogleAuthenticatorConfigBuilder().setTimeStepSizeInMillis(timeStepSizeInMillis).setWindowSize(windowSize) // 设置允许的时间窗口为 1 个时间步长.build();// 根据配置创建 GoogleAuthenticator 实例@SuppressWarnings("unused")GoogleAuthenticator gAuth = new GoogleAuthenticator(config);// 根据密钥创建一个 GoogleAuthenticatorKey 对象GoogleAuthenticatorKey key = new GoogleAuthenticatorKey.Builder(secretKey).build();// 生成一个可供 Google Authenticator 扫描的二维码链接,其中包含应用名称和用户邮箱信息String url = GoogleAuthenticatorQRGenerator.getOtpAuthURL(appName, email, key);// 对 URL 进行编码try{return URLEncoder.encode(url, StandardCharsets.UTF_8.name());}catch (UnsupportedEncodingException e){// 这里可以考虑记录日志,目前简单打印异常信息System.err.println("URL 编码时出现异常: " + e.getMessage());// 返回 null 表示生成失败,调用者可以根据返回值进行相应处理return null;}}/*** 根据密钥生成一个可供 Google Authenticator 扫描的二维码链接* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @param secretKey            用于生成二维码链接的密钥* @param appName              应用程序的名称* @param email                用户的邮箱地址* @param timeStepSizeInMillis 动态密码的时间步长(毫秒)* @return 生成的二维码链接*/public static String generateQRUrl(String secretKey, String appName, String email, long timeStepSizeInMillis){// 生成一个可供 Google Authenticator 扫描的二维码链接,其中包含应用名称和用户邮箱信息return generateQRUrl(secretKey, appName, email, timeStepSizeInMillis, WINDOW_SIZE);}/*** 根据密钥生成一个可供 Google Authenticator 扫描的二维码链接* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @param secretKey 用于生成二维码链接的密钥* @param appName   应用程序的名称* @param email     用户的邮箱地址* @return 生成的二维码链接*/public static String generateQRUrl(String secretKey, String appName, String email){// 生成一个可供 Google Authenticator 扫描的二维码链接,其中包含应用名称和用户邮箱信息return generateQRUrl(secretKey, appName, email, TIME_STEP_SIZE_IN_MILLIS, WINDOW_SIZE);}/*** 根据密钥生成当前时间对应的一次性动态密码* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @param secretKey            用于生成动态密码的密钥* @param timeStepSizeInMillis 动态密码的时间步长(毫秒)* @param windowSize           允许的时间窗口时间步长* @return 当前时间对应的一次性动态密码*/public static int generateCode(String secretKey, long timeStepSizeInMillis, int windowSize){// 构建 GoogleAuthenticator 的配置对象,设置时间步长GoogleAuthenticatorConfig config = new GoogleAuthenticatorConfig.GoogleAuthenticatorConfigBuilder().setTimeStepSizeInMillis(timeStepSizeInMillis).setWindowSize(windowSize) // 设置允许的时间窗口为 1 个时间步长.build();// 根据配置创建 GoogleAuthenticator 实例GoogleAuthenticator gAuth = new GoogleAuthenticator(config);// 利用密钥生成当前时间对应的一次性动态密码return gAuth.getTotpPassword(secretKey);}/*** 根据密钥生成当前时间对应的一次性动态密码* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @param secretKey            用于生成动态密码的密钥* @param timeStepSizeInMillis 动态密码的时间步长(毫秒)* @return 当前时间对应的一次性动态密码*/public static int generateCode(String secretKey, long timeStepSizeInMillis){// 利用密钥生成当前时间对应的一次性动态密码return generateCode(secretKey, timeStepSizeInMillis, WINDOW_SIZE);}/*** 根据密钥生成当前时间对应的一次性动态密码* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @param secretKey 用于生成动态密码的密钥* @return 当前时间对应的一次性动态密码*/public static int generateCode(String secretKey){// 利用密钥生成当前时间对应的一次性动态密码return generateCode(secretKey, TIME_STEP_SIZE_IN_MILLIS, WINDOW_SIZE);}/*** 验证输入的动态密码是否与根据密钥生成的密码匹配* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @param secretKey            用于验证的密钥* @param code                 待验证的动态密码* @param timeStepSizeInMillis 动态密码的时间步长(毫秒)* @param windowSize           允许的时间窗口时间步长* @return 若验证通过返回 true,否则返回 false*/public static boolean checkCode(String secretKey, int code, long timeStepSizeInMillis, int windowSize){// 构建 GoogleAuthenticator 的配置对象,设置时间步长GoogleAuthenticatorConfig config = new GoogleAuthenticatorConfig.GoogleAuthenticatorConfigBuilder().setTimeStepSizeInMillis(timeStepSizeInMillis).setWindowSize(windowSize) // 设置允许的时间窗口为 1 个时间步长.build();// 根据配置创建 GoogleAuthenticator 实例GoogleAuthenticator gAuth = new GoogleAuthenticator(config);// 验证输入的动态密码是否与根据密钥生成的密码匹配return gAuth.authorize(secretKey, code);}/*** 验证输入的动态密码是否与根据密钥生成的密码匹配* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @param secretKey            用于验证的密钥* @param code                 待验证的动态密码* @param timeStepSizeInMillis 动态密码的时间步长(毫秒)* @return 若验证通过返回 true,否则返回 false*/public static boolean verifyCode(String secretKey, int code, long timeStepSizeInMillis){// 验证输入的动态密码是否与根据密钥生成的密码匹配return checkCode(secretKey, code, timeStepSizeInMillis, WINDOW_SIZE);}/*** 验证输入的动态密码是否与根据密钥生成的密码匹配* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @param secretKey 用于验证的密钥* @param code      待验证的动态密码* @return 若验证通过返回 true,否则返回 false*/public static boolean verifyCode(String secretKey, int code){// 验证输入的动态密码是否与根据密钥生成的密码匹配return checkCode(secretKey, code, TIME_STEP_SIZE_IN_MILLIS, WINDOW_SIZE);}/*** 程序入口,用于测试动态密码生成和验证功能* * @author ZengWenFeng* @date 2025.04.16* @mobile 13805029595* @email 117791303@qq.com* @param args 命令行参数*/public static void main(String[] args){//// 生成一个用于生成动态密码的密钥String secretKey = generateSecretKey();System.out.println("Key  : " + secretKey);String appName = "ZengWenFeng";String userEmail = "117791303@ZengWenFeng.com";// 根据生成的密钥生成一个可供 Google Authenticator 扫描的二维码链接String qrCodeUrl = generateQRUrl(secretKey, appName, userEmail, TIME_STEP_SIZE_IN_MILLIS, WINDOW_SIZE);System.out.println("Url  : " + qrCodeUrl);// 利用生成的密钥生成当前时间对应的一次性动态密码int code = generateCode(secretKey, TIME_STEP_SIZE_IN_MILLIS, WINDOW_SIZE);System.out.println("Code  : " + code);// 验证生成的动态密码是否有效boolean isValid = checkCode(secretKey, code, TIME_STEP_SIZE_IN_MILLIS, WINDOW_SIZE);System.out.println("Valid : " + isValid);/*Secret Key: SRT5EAIQICUOWEI7QVPQ2DQ4JMQUTV67 QR Code URL:https://api.qrserver.com/v1/create-qr-code/?data=otpauth%3A%2F%2Ftotp%2FZengWenFeng%3A117791303%40ZengWenFeng.com%3Fsecret%3DSRT5EAIQICUOWEI7QVPQ2DQ4JMQUTV67%26issuer%3DZengWenFeng%26algorithm%3DSHA1%26digits%3D6%26period%3D30&size=200x200&ecc=M&margin=0 Current Code: 883702   Is Valid Code: true*/try{// 等待超过有效期,这里设置为 TIME_STEP_SIZE_IN_MILLIS + 1毫秒System.out.println("---------------------------------");System.out.println("Waiting for the code to expire...");Thread.sleep(TIME_STEP_SIZE_IN_MILLIS + 1);}catch (InterruptedException e){e.printStackTrace();}// 再次验证过期的动态密码boolean isExpiredValid = checkCode(secretKey, code, TIME_STEP_SIZE_IN_MILLIS, WINDOW_SIZE);System.out.println("Valid (after expiration): " + isExpiredValid);}
}

http://www.xdnf.cn/news/14977.html

相关文章:

  • Next.js 技术详解:构建现代化 Web 应用的全栈框架
  • ArcPy工具箱制作(下)
  • 51单片机实验一:点亮led灯
  • 每日一题---移动零
  • 第六章 进阶04 尊重
  • GreatSQL启动崩溃:jemalloc依赖缺失问题排查
  • 获取印度股票市场列表、查询IPO信息以及通过WebSocket实时接收数据
  • Git合并分支的两种常用方式`git merge`和`git cherry-pick`
  • 裸金属服务器有什么用途?
  • 数据仓库分层架构解析:从理论到实战的完整指南​​
  • 1. python开发小笔记
  • 【Semantic Kernel核心组件】planner:大模型时代的智能任务编排引擎
  • ASP.NET常见安全漏洞及修复方式
  • ARINC818协议(五)
  • xxljob 执行器流程-笔记
  • PHP腾讯云人脸核身生成 SDK 接口调用步骤使用签名
  • Vue3中provide和inject的用法示例
  • opencv函数展示3
  • Git LFS 学习笔记:原理、配置、实践与心路历程
  • 直播人脸美型核心技术详解:卷积神经网络与图像增强在美颜SDK中的应用
  • pdfjs库使用记录1
  • Web3区块链网络中数据隐私安全性探讨
  • 深度解析生成对抗网络:原理、应用与未来趋势
  • #systemverilog# 进程控制问题#(八)关于#0 问题的使用(三)
  • 全志H5,NanopiKP1lus移植QT5.12记录
  • 如何在 Electron 应用中安全地进行主进程与渲染器进程通信
  • 通过特定协议拉起 electron 应用
  • electron 渲染进程按钮创建新window,报BrowserWindow is not a constructor错误;
  • 嵌入式设备网络的动态ID分配机制实现
  • 极狐GitLab 用户 API 速率限制如何设置?