集成Google Authenticator实现多因素认证(MFA)
目录
- 参考
- 1、应用背景
- 2、多因素认证
- 3、谷歌google authenticator集成用法
- 3.1、原理
- 3.2、 MFA绑定
- 3.2.1、 用户输入用户名密码登录
- 3.2.2、检查是否已经绑定MFA(检查数据库是否保存该用户的google secret)
- 3.2.3、谷歌身份证认证器扫描绑定
- 3.2.4、手动测试验证码
- 3.3、基于OTP技术的MFA认证原理如下:
- 3.4、关键代码
- 3.4.1、调用LoginService的login方法进行登录(需传入手机上显示的6位动态验证码,否则校验不被通过)
- 3.4.2、GoogleAuthenticatorUtils提供了生成密钥、校验验证码是否和密钥匹配等功能
- 4、JumpServer 常用的 MFA 工具
- 安卓版:
- IOS版:
- 微信小程序:
- 商业产品:
参考
设计一个安全性架构时
手把手教你集成Google Authenticator实现多因素认证(MFA)
身份认证之多因素认证方法
谷歌身份验证器的正确使用方法
JupmServer堡垒机之MFA知识点说明
1、应用背景
多因素认证(Multi Factor Authentication,简称 MFA)的使用背景主要出于对账户和系统安全性的增强需求。传统的用户名和密码认证方式在面对日益复杂的网络威胁时显得不够安全,因为密码可能被泄露、猜测或被暴力破解。随着攻击者拥有越来越先进的工具,对更安全的认证协议的需求正在加大。多因素认证通过引入额外的认证因素,提供了更强大的安全层级。同时,将“实体所有”、“实体特征”、 “实体所知”三种不同认证因素结合起来增强系统或设备的安全性是研究人员容易设想的方向,因此多因素认证解决认证安全问题是大势所趋。
2、多因素认证
多因素认证是一种简单有效的安全实践方法,旨在提供两层或更多的身份验证保护。最常见的三种验证因素包括知识(实体所知)、持有物(实体所有)和固有属性(实体特征)。知识因素指的是用户知道的信息,如安全密保问题或个人识别号码如pin码;持有物因素是用户拥有的物品,例如SMS密码或硬件令牌;固有属性则与用户的身体特征有关,如指纹或面部识别等。这种方法提高了安全性,因为即使某个因素被泄露或破解,攻击者仍需要其他因素才能访问用户账户或系统。尤其是在面临日益复杂的网络安全威胁时,MFA的实施可以有效减少未经授权的访问,提高账户安全性。
三种验证因素可以总结如下:
基于实体所知的方法是最为广泛使用的方法,如密码、验证码等,其成本低、实现简单,但同时也面临较大安全威胁如暴力破解和木马侵入等。
基于实体所有的方法是安全性较高、成本较高的一类,主要应用在IC卡、门禁卡和数字签名等。但缺点是基于实体所有的方法因为存在固体实物,因此会面临着损坏和被复制的风险。
基于实体特征的方法是安全性最高的一种方式,通常采用生物识别方法进行验证。主要应用在指纹、虹膜、声波特征等验证方式。实体特性鉴别的准确性和效率主要取决于开发过程中的算法特征。
3、谷歌google authenticator集成用法
3.1、原理
基于OTP技术的MFA认证,是指在传统的用户名密码认证的基础上,增加一个额外的OTP认证。OTP是指一次性密码,每个OTP只能使用一次,有效期通常为30秒。
3.2、 MFA绑定
3.2.1、 用户输入用户名密码登录

3.2.2、检查是否已经绑定MFA(检查数据库是否保存该用户的google secret)
用户名密码登录成功后,检查是否已经绑定MFA(检查数据库是否保存该用户的google secret)
如果未绑定,则需要绑定MFA进行二次认证。
1、调用生产string secretKey = GoogleAuthenticatorUtils.createSecretKey(); 并入库;
2、利用谷歌库生成绑定二维码String keyUri = GoogleAuthenticatorUtils.createKeyUri(secretKey, username, “Demo_System”); // Demo_System 服务标识不参与运算,可任意设置

3.2.3、谷歌身份证认证器扫描绑定
前端弹出二维码,用户拿移动端打开谷歌身份证认证器app点击扫描绑定

3.2.4、手动测试验证码

3.3、基于OTP技术的MFA认证原理如下:
- 用户在登录时,首先输入用户名和密码。
- 服务器验证用户名和密码是否正确。
- 如果用户名和密码正确,前端提示输入MFA验证码。
- 用户在绑定认证过的设备上打开谷歌身份认证器查看当前时间点生成的OTP。
- 用户输入OTP,点击确定
- 服务器验证OTP是否正确。boolean verification = GoogleAuthenticatorUtils.verification(user.getGoogleAuthenticatorSecret(), loginParam.getMfaCode());
- 如果OTP正确,服务器允许用户登录。
3.4、关键代码
3.4.1、调用LoginService的login方法进行登录(需传入手机上显示的6位动态验证码,否则校验不被通过)
以下分享一次Spring Boot集成Goole Authenticator的案例关键性代码
@Service
public class LoginServiceImpl implements LoginService {private final UserService userService;public LoginServiceImpl(UserService userService) {this.userService = userService;}/*** 登录接口* @param loginParam {"username":"用户名", "password":"密码", "mfaCode":"手机应用Google Authenticator生成的验证码"}* @param servletRequest* @return*/@Overridepublic UserVo login(LoginParam loginParam, HttpServletRequest servletRequest) {// 校验用户名和密码是否匹配User user = getUserWithValidatePass(loginParam.getUsername(), loginParam.getPassword());// 验证数据库保存的密钥和输入的验证码是否匹配boolean verification = GoogleAuthenticatorUtils.verification(user.getGoogleAuthenticatorSecret(), loginParam.getMfaCode());if (!verification) {throw new BadRequestException("验证码校验失败");}// 用户信息保存到session中servletRequest.getSession().setAttribute("user", user);UserVo userVo = new UserVo();BeanUtils.copyProperties(user, userVo);return userVo;}/*** 生成二维码的Base64编码* 可以使用手机应用Google Authenticator来扫描二维码进行绑定* @param username* @param password* @return*/@Overridepublic String generateGoogleAuthQRCode(String username, String password) {// 校验用户名和密码是否匹配User user = getUserWithValidatePass(username, password);String secretKey;if (StringUtils.isEmpty(user.getGoogleAuthenticatorSecret())) {secretKey = GoogleAuthenticatorUtils.createSecretKey();}else {secretKey = user.getGoogleAuthenticatorSecret();}// 生成二维码String qrStr;try(ByteArrayOutputStream bos = new ByteArrayOutputStream()){String keyUri = GoogleAuthenticatorUtils.createKeyUri(secretKey, username, "Demo_System"); // Demo_System 服务标识不参与运算,可任意设置QRCodeUtils.writeToStream(keyUri, bos);qrStr = Base64.encodeBase64String(bos.toByteArray());}catch (WriterException | IOException e) {throw new ServiceException("生成二维码失败", e);}if (StringUtils.isEmpty(qrStr)) {throw new ServiceException("生成二维码失败");}user.setGoogleAuthenticatorSecret(secretKey);userService.updateById(user);return "data:image/png;base64," + qrStr;}private User getUserWithValidatePass(String username, String password) {String mismatchTip = "用户名或者密码不正确";// 根据用户名查询用户信息User user = userService.getByUsername(username).orElseThrow(() -> new BadRequestException(mismatchTip));// 比对密码是否正确String encryptPassword = SecureUtil.md5(password);if (!encryptPassword.equals(user.getPassword())) {throw new BadRequestException(mismatchTip);}return user;}
}
3.4.2、GoogleAuthenticatorUtils提供了生成密钥、校验验证码是否和密钥匹配等功能
public class GoogleAuthenticatorUtils {/*** 时间前后偏移量* 用于防止客户端时间不精确导致生成的TOTP与服务器端的TOTP一直不一致* 如果为0,当前时间为 10:10:15* 则表明在 10:10:00-10:10:30 之间生成的TOTP 能校验通过* 如果为1,则表明在* 10:09:30-10:10:00* 10:10:00-10:10:30* 10:10:30-10:11:00 之间生成的TOTP 能校验通过* 以此类推*/private static final int TIME_OFFSET = 0;/*** 创建密钥*/public static String createSecretKey() {SecureRandom random = new SecureRandom();byte[] bytes = new byte[20];random.nextBytes(bytes);return Base32.encode(bytes).toLowerCase();}/*** 根据密钥获取验证码* 返回字符串是因为数值有可能以0开头* @param secretKey 密钥* @param time 第几个30秒 System.currentTimeMillis() / 1000 / 30*/public static String generateTOTP(String secretKey, long time) {byte[] bytes = Base32.decode(secretKey.toUpperCase());String hexKey =HexUtil.encodeHexStr(bytes);String hexTime = Long.toHexString(time);return TOTP.generateTOTP(hexKey, hexTime, "6");}/*** 生成 Google Authenticator Key Uri* Google Authenticator 规定的 Key Uri 格式: otpauth://totp/{issuer}:{account}?secret={secret}&issuer={issuer}* https://github.com/google/google-authenticator/wiki/Key-Uri-Format* 参数需要进行 url 编码 +号需要替换成%20* @param secret 密钥 使用 createSecretKey 方法生成* @param account 用户账户 如: example@domain.com* @param issuer 服务名称 如: Google,GitHub* @throws UnsupportedEncodingException*/@SneakyThrowspublic static String createKeyUri(String secret, String account, String issuer) throws UnsupportedEncodingException {String qrCodeStr = "otpauth://totp/${issuer}:${account}?secret=${secret}&issuer=${issuer}";ImmutableMap.Builder<String, String> mapBuilder = ImmutableMap.builder();mapBuilder.put("account", URLEncoder.encode(account, "UTF-8").replace("+", "%20"));mapBuilder.put("secret", URLEncoder.encode(secret, "UTF-8").replace("+", "%20"));mapBuilder.put("issuer", URLEncoder.encode(issuer, "UTF-8").replace("+", "%20"));return StringSubstitutor.replace(qrCodeStr, mapBuilder.build());}/*** 校验方法** @param secretKey 密钥* @param totpCode TOTP 一次性密码* @return 验证结果*/public static boolean verification(String secretKey, String totpCode) {long time = System.currentTimeMillis() / 1000 / 30;// 优先计算当前时间,然后再计算偏移量,因为大部分情况下客户端与服务的时间一致if (totpCode.equals(generateTOTP(secretKey, time))) {return true;}for (int i = -TIME_OFFSET; i <= TIME_OFFSET; i++) {// i == 0 的情况已经算过if (i != 0) {if (totpCode.equals(generateTOTP(secretKey, time + i))) {return true;}}}return false;}}
4、JumpServer 常用的 MFA 工具
安卓版:
- google authenticator
- microsoft authenticator
- 阿里云 App 虚拟 MFA
- CKEY 令牌
IOS版:
- google authenticator
- microsoft authenticator
- 阿里云 app 虚拟 MFA
微信小程序:
- MinaOTP
- MFA Authentication
- CKEY 令牌
商业产品:
- 宁盾
相关文章:
集成Google Authenticator实现多因素认证(MFA)
目录 参考1、应用背景2、多因素认证3、谷歌google authenticator集成用法3.1、原理3.2、 MFA绑定3.2.1、 用户输入用户名密码登录3.2.2、检查是否已经绑定MFA(检查数据库是否保存该用户的google secret)3.2.3、谷歌身份证认证器扫描绑定3.2.4、手动测试验…...
网关(Gateway)- 自定义过滤器工厂
自定义过滤工厂类 DemoGatewayFilterFactory package com.learning.springcloud.custom;import org.apache.commons.lang.StringUtils; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChai…...
HTML静态网页成品作业(HTML+CSS)—— 香奈儿香水介绍网页(1个页面)
🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有1个页面。 二、作品演示 三、代…...
C++11 lambda表达式和包装器
C11 lambda表达式和包装器 一.lambda表达式1.lambda表达式的引入2.基本语法和使用1.基本语法2.使用1.传值捕捉的错误之处2.传引用捕捉 3.lambda表达式的底层原理4.lambda的特殊之处5.lambda配合decltype的新玩法 二.function包装器1.概念2.包装函数1.包装普通函数2.包装成员函数…...
3. MySQL 数据表的基本操作
文章目录 【 1. MySQL 创建数据表 】【 2. MySQL 查看表 】2.1 查看表的属性DESCRIBE/DESC 以表格的形式展示表属性SHOW CREATE TABLE 以SQL语句的形式展示表属性 2.2 查看表的内容 【 3. MySQL 修改数据表结构 】3.1 修改表名3.2 修改表字符集3.3 添加字段在末尾添加字段在开头…...
Linux命令篇(一):文件管理部分
💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 文章目录 1、cat命令常用参…...
IP协议1.0
基本概念: • 主机: 配有IP地址, 但是不进⾏路由控制的设备; • 路由器: 即配有IP地址, ⼜能进⾏路由控制; • 节点: 主机和路由器的统称; IP协议的报头 • 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4. • 4位头部⻓度(header length): IP头部的⻓…...
源码编译安装LNMP
LNMP包含: linux、Nginx、Mysql、php LNMP的工作原理 : 由客户端发送页面请求给Nginx,Nginx会根据location匹配用户访问请求的URL路径判断是静态还是动态,静态的一般是以 .html .htm .css .shtml结尾,动态的一般是以 .…...
安装Chrome扩展程序来 一键禁用页面上的所有动画和过渡。有那些扩展程序推荐一下
要安装Chrome扩展程序来一键禁用页面上的所有动画和过渡,以下是一些推荐的扩展程序: Toggle CSS Animations and Transitions 功能:此扩展程序允许用户轻松地在网页上切换CSS动画和过渡的开启与关闭状态。使用方法:安装后&#x…...
读人工智能时代与人类未来笔记19_读后总结与感想兼导读
1. 基本信息 人工智能时代与人类未来 (美)亨利基辛格,(美)埃里克施密特,(美)丹尼尔胡滕洛赫尔 著 中信出版社,2023年6月出版 1.1. 读薄率 书籍总字数145千字,笔记总字数39934字。 读薄率39934145000≈27.5% 1.2. 读厚方向 千脑智能 脑机穿越 未来呼啸而来 …...
个人影响力
华人出了个黄仁勋,世界级影响力,还是近代华人历史首次出现具有如此影响力的人。凭借的逻辑是什呢?在人工智能领域有巨大影响力。...
OBS实现多路并发推流
OBS实现多路并发推流 解决方案速览相关依赖下载安装多路推流 解决方案速览 利用OBS进行本地直播画面的构建。 使用Multiple RTMP outputs plugin进行多路并发推流。 相关依赖下载安装 OBS软件 # OBS官网 https://obsproject.com/zh-cnMultiple RTMP outputs plugin # 插件官网…...
JDK环境配置、安装
DK环境配置(备注:分32位与64位JDK,32位电脑只能按照32位JDK,64位电脑兼容32、64位JDK) 一、检查自己电脑是否安装过JDK 1.在电脑屏幕左下角,输入命令提示符CMD,打开命令提示符应用 2.在打开界…...
莱富康压缩机的选型软件介绍
下载地址 https://download.csdn.net/download/jintaihu/16295771 安装步骤 这里可以选制冷系统的参数,最后在压缩机列表内选择推荐的型号。...
Pr 2024下载安装,Adobe Premiere专业视频编辑软件安装包获取!
Premiere Pro,简称PR,无论是想要剪辑家庭录像,还是制作专业的影视作品,Premiere Pro都能为您提供强大的支持。 Premiere Pro以其卓越的编辑功能和强大的性能,助力用户在视频创作的道路上不断突破自我。 它具备丰富的视…...
MySQL事务与MVCC
文章目录 事务和事务的隔离级别1.为什么需要事务2.事务特性1_原子性(atomicity)2_一致性(consistency)3_持久性(durability)4_隔离性(isolation) 3.事务并发引发的问题1_脏读2_不可重…...
【数据结构】链式二叉树详解
个人主页~ 链式二叉树基本内容~ 链式二叉树详解 1、通过前序遍历的数组来构建二叉树2、二叉树的销毁3、二叉树节点个数4、二叉树叶子节点个数5、二叉树第k层节点个数6、二叉树查找7、前序遍历8、中序遍历9、后序遍历10、层序遍历与检查二叉树是否为完全二叉树Queue.hQueue.c层序…...
PHP面向对象编程总结
PHP面向对象编程总结 学习PHP时,面向对象编程(OOP)往往是一个重要的里程碑。PHP的OOP功能提供了一种更加模块化、可扩展和易于维护的代码结构。在本文中,我们将深入探讨PHP面向对象编程的各个方面,包括类与对象、访问控…...
linux中的“->“符号
问: "->“符号在Linux中是什么意思。 例如:当我在一个特定的文件夹中执行ls -l时,我得到了以下结果。 lrwxrwxrwx 1 root root 11 May 16 13:30 nexus3 -> /nexus-data lrwxrwxrwx 1 root root 29 Feb 27 12:23 ojdbc.jar -&g…...
MySql 数据类型选择与优化
选择优化的数据类型 更小的通常更好 一般情况下尽量使用可以正确存储数据的最小类型。更小的数据类型通常更快,因为它们占用更少的磁盘,内存和CPU缓存,并且处理时需要的CPU周期也更少。但也要确保没有低估需要存储值的范围。 简单就好 简单的…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
