如何开发两步验证功能

article/2025/10/6 14:38:47

什么是两步验证

  两步验证,是指用户登录账户的时候,除了要输入用户名和密码,还要求用户输入一个动态密码,为帐户添加了一层额外保护。这个动态密码要么是专门的硬件,要么由用户手机APP提供。即使入侵者窃取了用户密码,也会因不能使用用户手机而无法登录帐户。许多游戏客户端和网银采用这种方式。以银行为例,当用户进行转账操作时,第一步输入6位取款密码,第二步输入动态密码器上数字,这个密码器是开户时银行提供的硬件。
fc0617ba6b2062bec68c87eb481d25c1_hd.jpg

动态密码原理

  客户端和服务器事先协商好一个密钥K,用于一次性密码的生成过程,此密钥不被任何第三方所知道。此外,客户端和服务器各有一个计数器C,并且事先将计数值同步。进行验证时,客户端对密钥和计数器的组合(K,C)使用HMAC(Hash-based Message Authentication Code)算法计算一次性密码,公式如下:HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))上面采用了HMAC-SHA-1,当然也可以使用HMAC-MD5等。HMAC算法得出的值位数比较多,不方便用户输入,因此需要截断(Truncate)成为一组不太长十进制数(例如6位)。计算完成之后客户端计数器C计数值加1。用户将这一组十进制数输入并且提交之后,服务器端同样的计算,并且与用户提交的数值比较,如果相同,则验证通过,服务器端将计数值C增加1。如果不相同,则验证失败。

业务流程

  如何开发这个功能呢?我们先理清它的流程:

  1. 第一步:输入常规帐号密码,验证成功后进入二次验证页面。
  2. 第二步:二次验证页面要求用户输入动态密码,用户手机必须先通过APP绑定帐号后才能获取动态密码,APP推荐eagle2fa。
  3. 第三步:页面生成二维码,内容是URI地址otpauth://totp/账号?secret=密钥,用eagle2fa扫码后绑定帐号,把密钥保存在客户端,如下图所示:
    o_eagle2fa.png
  4. 第四步:输入APP上的6位数字,验证通过进入用户中心页面。
    最重要的功能是生成二维码验证动态密码

组件选型

googleauth是Google Authenticator的开源实现

    <dependency><groupId>com.warrenstrange</groupId><artifactId>googleauth</artifactId><version>1.1.2</version></dependency>

zxing用于生成二维码图片

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

也可以使用其他网站提供的的WEB API,譬如:

http://qr.liantu.com/api.php?text=x
x必须用UTF8编码格式,x内容出现&符号时用%26代替,换行符使用%0A

关键代码

以下代码演示怎么使用GoogleAuthenticator包:

    private static final GoogleAuthenticator googleAuthenticator = new GoogleAuthenticator();/*** 由于只是演示,dao没有操作数据库,真实的场景必然要持久化*/@Autowiredprivate UserDao userDao;@PostConstructpublic void init() {googleAuthenticator.setCredentialRepository(new ICredentialRepository() {@Overridepublic String getSecretKey(String userName) {//根据帐号查询secretKeyreturn userDao.getSecretKey(userName);}@Overridepublic void saveUserCredentials(String userName, String secretKey, int validationCode, List<Integer> scratchCodes) {//secretKey要保存在数据库中userDao.saveUserCredentials(userName, secretKey);}});log.info("GoogleAuthenticator初始化成功");}

以下代码是生成二维码,uri的格式不能写错。

    // 必须按照这个格式,APP才能正常绑定private static final String KEY_FORMAT = "otpauth://totp/%s?secret=%s";/*** 生成二维码链接*/private String getQrUrl(String username) {//每次调用createCredentials都会生成新的secretKeyGoogleAuthenticatorKey key = googleAuthenticator.createCredentials(username);log.info("username={},secretKey={}", username, key.getKey());return String.format(KEY_FORMAT, username, key.getKey());}

以下是二次验证方法:

    // 验证动态密码  username 帐号, code  app上的6位数字public boolean validCode(String username, int code) {return googleAuthenticator.authorizeUser(username, code);}

点击获取完整代码

参考(部分摘抄的文字版权属于原作者)

https://blog.seetee.me/post/2011/google-two-step-verification/
https://www.zhihu.com/question/20462696/answer/19670601

转载于:https://www.cnblogs.com/xiaoyangjia/p/11512453.html


http://chatgpt.dhexx.cn/article/tEI4qLkP.shtml

相关文章

兩步验证的原理

被盗号 “您的账号密码有误,请重新输入” 小卢盯着电脑屏幕看了5分钟,心里纳闷,昨天还能登录,怎么今天就密码错误了,难不成我被盗号了?想到这里,小卢赶紧给自己的程序员好友小王打电话。 小卢:“小王,我在XX网站的账号被盗了!” 小王:“确定被盗了?赶紧把密码找…

(01)Webrtc::Fec与Nack的二三事

写在前面&#xff1a;要理解Fec与Nack逻辑&#xff0c;我喜欢先从接受端看&#xff0c; 理解了Fec与Nack是如何被使用的&#xff0c;才能更好的明白不同的机制应该怎么用&#xff0c;在什么场合用。 更新丢包逻辑 void PacketBuffer::UpdateMissingPackets(uint16_t seq_num)…

Channel closed; cannot ack/nack

再一次用rabbmitmq的时候遇到了 Channel closed&#xff1b; cannot ack/nack的异常信息&#xff0c;这个可能是因为rabbmitmq默认的模式是自动ack&#xff0c;我没有配置手动ack 然后在代码里又basicack了。 MessageProperties properties message.getMessageProperties();l…

简述WebRTC中的丢包重传Nack的实现

一 简述 接收端发现序列号不连续&#xff0c;发送RTCP FB Nack包&#xff0c;发送端从历史队列中查找该包&#xff0c;再发送RTP包&#xff0c;但WebRTC用的RTX重发该包&#xff0c;ssrc和原视频流不同&#xff0c;pt也不同。 artpmap:96 H264/90000 artcp-fb:96 goog-remb a…

WEBRTC浅析(五)视频Nack包的发送判断逻辑以及数据流

这篇文章是对webrtc 中Nack包发送机制的梳理&#xff0c;主要包括三个部分&#xff1a; 第一部分&#xff0c;介绍RTCP包中&#xff0c;Nack包的规范。 第二部分&#xff0c;介绍在WEBRTC中&#xff0c;Nack发送机制的数据流程图。 第三部分&#xff0c;介绍在WEBRTC中&#xf…

RabbitMQ的ack和nack机制

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、ACK机制二、主动ACK三、手动ACK四、Nack机制五、MQ unack的影响总结 前言 本文主要讨论RabbitMQ消费者的ack和nack机制&#xff0c;并且关注ack和nack使用…

RTCP 协议的 NACK 报文

接收方定时把所有未收到的包序号通过反馈报文通知到发送方进行重传。 相对 ARQ带来的改进&#xff1a;减少的反馈包的频率和带宽占用&#xff0c;同时也能比较及时地通知发送方进行丢包重传。 NACK 报文的定义在 [rfc4585] 文档中定义。 RTCP 的反馈报文包头定义如下&#x…

webrtc nack实现原理

1.nack 简介 webrtc 中nack是最基本的QOS策略&#xff0c;与ack机制不同的地方是nack是接收端检测到丢包时&#xff0c;告知发送端具体丢包的序号&#xff0c;接收端收到nack后从缓存中找到对应的包并发送出去。 2. nack实现 nack rtcp报文格式如上图所示&#xff0c;pt205。P…

webrtc QOS方法一(NACK实现)

一&#xff1a;概述 NACK则在接收端检测到数据丢包后&#xff0c;发送NACK报文到发送端&#xff1b;发送端根据NACK报文中的序列号&#xff0c;在发送缓冲区找到对应的数据包&#xff0c;重新发送到接收端。NACK需要发送端发送缓冲区的支持&#xff0c;RFC5104[2]定义NACK数据包…

认识网络通信中的 ACK、NACK 和 REX

ACK、NACK、 REX在面试或者网络通信的时候&#xff0c;我们可能经常听到和遇到。今天就来详细介绍一下ACK、NACK、 REX。 认识ACK、NACK、 REX ACK&#xff1a;Acknowledgement&#xff0c;它是一种正向反馈&#xff0c;接收方收到数据后回复消息告知发送方。NACK&#xff1a…

WebRTC之NACK、RTX 在什么时机判断丢包发送NACK请求和RTX丢包重传

WebRTC之NACK、RTX 在什么时机判断丢包发送NACK请求和RTX丢包重传 WebRTC之NACK、RTX 在什么时机判断丢包发送NACK请求和RTX丢包重传 WebRTC之NACK、RTX 在什么时机判断丢包发送NACK请求和RTX丢包重传前言一、NACK与RTX的作用1、NACK/RTX的工作机制的流程图2、NACK/RTX涉及到的…

WebRTC 的音频弱网对抗之 NACK

本文梳理 WebRTC 的音频弱网对抗中的 NACK 机制的实现。音频的 NACK 机制在 WebRTC 中默认是关闭的&#xff0c;本文会介绍开启 NACK 机制的方法。 在网络数据传输中&#xff0c;NACK (NAK&#xff0c;negative acknowledgment&#xff0c;not acknowledged) 是数据接收端主动…

流媒体弱网优化之路(NACK)——纯NACK方案的优化探索

流媒体弱网优化之路(NACK)——纯NACK方案的优化探索 —— 我正在的github给大家开发一个用于做实验的项目 —— github.com/qw225967/Bifrost目标&#xff1a;可以让大家熟悉各类Qos能力、带宽估计能力&#xff0c;提供每个环节关键参数调节接口并实现一个json全配置&#xff…

WebRTC源码分析 nack详解

1、Nack过程 1.1 nack是什么 丢包重传(NACK)是抵抗网络错误的重要手段。NACK在接收端检测到数据丢包后&#xff0c;发送NACK报文到发送端&#xff1b;发送端根据NACK报文中的序列号&#xff0c;在发送缓冲区找到对应的数据包&#xff0c;重新发送到接收端。NACK需要发送端&am…

谈谈网络通信中的 ACK、NACK 和 REX

目录 名词解释 问题 1&#xff1a; 接收方如何判断数据包是否丢失&#xff1f; 问题 2&#xff1a;发送方如何确认数据包已经丢失&#xff1f; 问题 3&#xff1a;重传超时的计算规则&#xff1f; 问题 4&#xff1a;发送方的数据包要缓存多久&#xff1f; 问题 5&#x…

费马定理_高数_1元微积分

定理 设 f(x) 在 x0 点处满足&#xff1a;1、可导 2、取得极值&#xff0c;则有 f ’ (x0)0 证明 不妨假设 f(x) 在点 x0 处取得极大值&#xff0c;则存在 x0 的邻域 U( x0 )&#xff0c;对任意的 x属于U( x0 )&#xff0c;都有 根据导数定义与极限的保号性有 又 f(x) 在点…

老猿Python博客文章目录索引

本目录提供老猿Python所有相关博文的一级目录汇总&#xff0c;带星号的为付费专栏&#xff1a; 一、专栏列表 本部分为老猿所有专栏的列表&#xff0c;每个专栏都有该专栏置顶的博文目录&#xff1a; Python基础教程目录PyQt入门学习* 使用PyQt开发图形界面Python应用PyQtmo…

(组合数+快速幂+lucas+费马小引理)acwing 887. 求组合数 III

887. 求组合数 III 题目链接https://www.acwing.com/problem/content/889/ 题目&#xff1a; 思路&#xff1a; #include<iostream> #include<cstdio> using namespace std; typedef long long LL; int n; int qmi(LL a,int k,int p){int res1;while(k){if(k&…

(组合数 +快速幂+逆元+费马小引理)acwing 886. 求组合数 II

886. 求组合数 II 题目链接https://www.acwing.com/problem/content/888/ 题目&#xff1a; 思路&#xff1a; #include<iostream> #include<cstdio> using namespace std; typedef long long LL; const int mod1e97;//mod为质数 int a,b,n; int fact[100010],…