TOTP双因素认证(2FA)php简单实现

TOTP身份验证的工作原理基于时间戳和密钥。用户需要在设置阶段将密钥与相应的身份验证器进行绑定。通常,用户会在需要使用TOTP动态验证码的APP或网站上获得一个密钥,然后将该密钥添加到TOTP验证器工具上。验证器会根据当前的时间戳和密钥生成一个一次性密码(通常是6位数字),用户需要将这个密码输入到需要验证的系统中以完成身份验证。

1、针对某个登录用户生成秘钥

<?php
//生成32位的秘钥
function generateSecret($length = 32) {$characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; // Base32 字符集$secret = '';for ($i = 0; $i < $length; $i++) {$secret .= $characters[random_int(0, strlen($characters) - 1)];}return $secret;
}$secret = generateSecret(); // 用户的唯一 Secret
echo "Secret Key: $secret";

2、生成某个登录用户需要绑定到Authenticator的链接(二维码形式显示)

<?php
function generateQRCodeUrl($appName, $userEmail, $secret) {$issuer = urlencode($appName);$email = urlencode($userEmail);return "otpauth://totp/{$issuer}:{$email}?secret={$secret}&issuer={$issuer}";
}$appName = "xxx-test";//在app列表中显示的名称
$userEmail = "xxx.xxx@gmail.com";
$secret='4IRT6WN2RHWZHJ4ZOO2POMYB6W43FQ7G';
$qrCodeUrl = generateQRCodeUrl($appName, $userEmail, $secret);
echo $qrCodeUrl;//当前链接生成为二维码的链接
//echo '<img src="' . $qrCodeUrl . '" alt="QR Code">';

3、登录的时候验证用户输入的code是否正确

<?php
/*** 生成动态验证码(验证用)*/
function getOtp($secret, $timeSlice = null) {if ($timeSlice === null) {$timeSlice = floor(time() / 30); // 当前时间戳除以30秒}$secretKey = base32Decode($secret); // 解码 Base32 密钥$time = pack('N*', 0) . pack('N*', $timeSlice); // 将时间戳转换为 64 位二进制// 使用 HMAC-SHA1 计算哈希值$hmac = hash_hmac('sha1', $time, $secretKey, true);// 截取动态偏移量$offset = ord(substr($hmac, -1)) & 0x0F;$binary = (ord($hmac[$offset]) & 0x7F) << 24 |(ord($hmac[$offset + 1]) & 0xFF) << 16 |(ord($hmac[$offset + 2]) & 0xFF) << 8 |(ord($hmac[$offset + 3]) & 0xFF);// 生成6位数字验证码return str_pad($binary % pow(10, 6), 6, '0', STR_PAD_LEFT);
}function base32Decode($base32) {$characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';$base32 = strtoupper($base32);$bits = '';foreach (str_split($base32) as $char) {$bits .= str_pad(decbin(strpos($characters, $char)), 5, '0', STR_PAD_LEFT);}$bytes = '';foreach (str_split($bits, 8) as $byte) {$bytes .= chr(bindec($byte));}return $bytes;
}// $otp = getOtp($secret);
// echo "Generated OTP: $otp".PHP_EOL;
//验证方法
function verifyOtp($secret, $userInput, $window = 1) {$timeSlice = floor(time() / 30);//TOTP 的核心是基于当前时间的30秒时间片。一个时间片的公式是for ($i = -$window; $i <= $window; $i++) {echo "OTP: " . getOtp($secret, $timeSlice + $i) . PHP_EOL;echo "$i:$window".PHP_EOL;if (getOtp($secret, $timeSlice + $i) === $userInput) {return true;}}return false;
}
//index.php 生成的secret
$secret='4IRT6WN2RHWZHJ4ZOO2POMYB6W43FQ7G';
$userInput = '927055'; // 用户输入的动态验证码
if (verifyOtp($secret, $userInput)) {echo "验证通过!";
} else {echo "验证码错误,请重试。";
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/64239.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day21——web自动化测试(3)Unittest+Selenium实战小案例

【没有所谓的运气&#x1f36c;&#xff0c;只有绝对的努力✊】 目录 今日目标&#xff1a; 1、UnitTest框架 2、UnitTest 核心用例 2.1 TestCase 2.2 TestSuite 2.3 TestRunner 2.4 TestLoader 2.5 TestLoader 与 TestSuite的区别 2.6 Fixture 3、断言 3.1 1230…

【Flink运行时架构】系统构架

SMP架构 数据处理系统的架构最简单的实现方式就是单节点&#xff0c;但是随着数据量的增大&#xff0c;为了使单节点的机器性能更加强大&#xff0c;需要增加CPU数量和加大内存来提高吞吐量。这就是所谓的SMP(Symmetrical Multi Processing,对称多处理)架构。 但是这种架构带来…

CountDownLatch应用举例

定义 CountDownLatch是juc下的一个多线程锁&#xff0c;下面是jdk对它的定义 A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes. 翻译如下 一种同步辅助工具&#xff0c;允许一个或多个…

ADC(二):外部触发

有关ADC的基础知识请参考标准库入门教程 ADC&#xff08;二&#xff09;&#xff1a;外部触发 1、TIM1的CC1事件触发ADC1DMA重装载2、TIM3的TRGO事件(的更新事件)触发ADC1DMA重装载3、TIM3的TRGO事件(的捕获事件)触发ADC1DMA重装载4、优化TIM3的TRGO事件(的捕获事件)触发ADC1D…

磁盘分区格式

MBR和GPT ‌磁盘分区形式主要有两种&#xff1a;MBR和GPT。‌‌ MBR&#xff08;Master Boot Record&#xff09; MBR是一种较旧的分区形式&#xff0c;首次引入于1983年的IBM PC DOS 2.0。它位于驱动器的第一个扇区&#xff0c;包含460字节的引导代码、64字节的磁盘分区表和…

几个支持用户名密码的代理链工具: glider, gost, proxychains+microsocks

几个支持用户名密码的代理链工具: glider, gost, proxychainsmicrosocks gost -L:7777 -Fsocks5://192.168.2.20:7575 -Fsocks5://user:passwd1.1.1.1:10086 -Dgost&#xff1a;(https://github.com/ginuerzh/gost) 参考 https://www.quakemachinex.com/blog/279.html

量子退火与机器学习(1):少量数据求解未知QUBO矩阵,以少见多

文章目录 前言ー、复习QUBO&#xff1a;中药配伍的复杂性1.QUBO 的介入&#xff1a;寻找最佳药材组合 二、难题&#xff1a;QUBO矩阵未知的问题1.为什么这么难&#xff1f; 三、稀疏建模(Sparse Modeling)1. 欠定系统中的稀疏解2. L1和L2的选择&#xff1a; 三、压缩感知算法(C…

【连续学习之SSL算法】2018年论文Selfless sequential learning

1 介绍 年份&#xff1a;2018 期刊&#xff1a; arXiv preprint Aljundi R, Rohrbach M, Tuytelaars T. Selfless sequential learning[J]. arXiv preprint arXiv:1806.05421, 2018. 本文提出了一种名为SLNID&#xff08;Sparse coding through Local Neural Inhibition and…

关于SNAT、DNAT及浮动地址

SNAT、DNAT SNAT、DNAT就是实现代理的功能。 SNAT 类似于客户端代理&#xff1a;内网主机通过共享公网 IP 地址访问外部服务。DNAT 类似于服务端代理&#xff1a;外部请求通过公网 IP 转发到内网主机上的服务。 没有大网地址的内部主机想要作为客户端访问外部网络&#xff08;主…

结构方程模型【SEM】:嵌套分层数据及数据分组分析

结构方程模型&#xff08;System of Equations Model&#xff0c;简称SEM&#xff09;&#xff0c;在生态学和环境科学中通常指的是一组描述生态系统中能量、物质和信息流动的数学方程。这些方程可以是确定性的&#xff0c;也可以是随机的&#xff0c;它们共同构成了一个模型&a…

hot100_56. 合并区间

以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。 请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。数据结构 二维链表存储每个区间 方法 先对每个区间的…

Python大数据:基于Python的王者荣耀战队数据分析系统的设计与实现

系统展示 比赛信息管理 看板展示 系统管理 摘要 本文使用Python与MYSQL技术搭建了一个王者荣耀战队的数据分析系统。对用户提出的功能进行合理分析&#xff0c;然后搭建开发平台以及配置计算机软硬件&#xff1b;通过对数据流图以及系统结构的设计&#xff0c;创建相应的数据…

两分钟解决:vscode卡在设置SSH主机,VS Code-正在本地初始化VSCode服务器

问题原因 remote-ssh还是有一些bug的&#xff0c;在跟新之后可能会一直加载初始化SSH主机解决方案 1.打开终端2.登录链接vscode的账号&#xff0c;到家目录下3.找到 .vscode-server文件,删掉这个文件4.重启 vscode 就没问题了

深入理解与优化Java二维数组:从定义到性能提升的全面指南

1. 定义和初始化二维数组 在Java中&#xff0c;二维数组可以看作是数组的数组。你可以将它想象成一个矩阵或表格&#xff0c;每个元素是一个数组。 1.1 定义二维数组 二维数组的定义语法如下&#xff1a; datatype[][] arrayName;datatype 是数组元素的数据类型。arrayName…

day26 文件io

函数接口 1 .open和close 文件描述符&#xff1a;系统为用open打开的文件分配的标识符 非负的整形数据 0-1023 最小未被使用原则 使用完时及时释放&#xff0c;避免文件描述符溢出 文件描述溢出就是文件使用完没有及时关闭文件 int open(const char *pathname, int flags); /…

Java Stream流详解——串行版

Stream流——串行版 ​ Stream流是java8引入的特性&#xff0c;极大的方便了我们对于程序内数据的操作&#xff0c;提高了性能。通过函数式编程解决复杂问题。 1.BaseStream<T,S extense BaseStream<T,S>> ​ 他是流处理的基石概念&#xff0c;重点不在于这个接…

el-backtop(返回顶部)

案例&#xff1a; <el-backtop target".app-main"><svg-icon icon-class"backtop" size"24px" /></el-backtop>

探秘“香水的 ChatGPT”:AI 开启嗅觉奇幻之旅!

你没有看错&#xff0c;AI也能闻到味道了&#xff01;这是一家名为Osmo公司公布的信息&#xff0c;他们成功创造出了由AI生成的李子味道&#xff0c;快跟着小编一探究竟吧~ 【图片来源于网络&#xff0c;侵删】 Osmo公司的这项技术&#xff0c;通过分析香味的化学成分和人类嗅…

Vue3入门(9)

1. 【 replace属性】 作用&#xff1a;控制路由跳转时操作浏览器历史记录的模式。 浏览器的历史记录有两种写入方式&#xff1a;分别为push和replace&#xff1a; - push是追加历史记录&#xff08;默认值&#xff09;。 - replace是替换当前记录。 . 开启replace模式&#xff…

第十九章 C++ 日期 时间

C 日期 & 时间 C 标准库没有提供所谓的日期类型。C 继承了 C 语言用于日期和时间操作的结构和函数。为了使用日期和时间相关的函数和结构&#xff0c;需要在 C 程序中引用 <ctime> 头文件。 有四个与时间相关的类型&#xff1a;clock_t、time_t、size_t 和 tm。类型…