我最近在项目中遇到需要在登录的时候加入双因素验证系统的功能需求, 整体步骤感觉还是有必要写下来,方便做类似功能的同学能够借鉴。

google-Authenticator在国内可能并不适用,于是需要寻找一个能在国内稳定使用的二次验证系统

微软的Microsoft-Authenticator二次验证系统可以说是比较合适的

官方的二次验证的流程如下:

首先是需要一个工具类

@Component
public class TwoFactorAuthUtil {@Autowiredprivate ParameterStubV1 parameterStubV1;/*** 生成二维码内容    网站地址(可不写)* @return*/public static String getQrCodeText(String secretKey, String account, String issuer) {String normalizedBase32Key = secretKey.replace(" ", "").toUpperCase();try {String Url = null;Url = "otpauth://totp/"+ URLEncoder.encode((!StringUtils.isEmpty(issuer) ? (issuer + ":") : "") + account, "UTF-8").replace("+", "%20")+ "?secret=" + URLEncoder.encode(normalizedBase32Key, "UTF-8").replace("+", "%20")+ (!StringUtils.isEmpty(issuer) ? ("&issuer=" + URLEncoder.encode(issuer, "UTF-8").replace("+", "%20")) : "");//log.info(Url);return Url;} catch (UnsupportedEncodingException e) {throw new IllegalStateException(e);}}/*** description:* @author 获取二维码*/public String getQrCode(String loginName, String newSecretKey) {String base64Image = null;try {// 生成二维码内容String qrCodeText = getQrCodeText(newSecretKey, loginName, "");int width = 300; // 图片宽度int height = 300; // 图片高度try {// 将URL转换为BitMatrixQRCodeWriter qrCodeWriter = new QRCodeWriter();BitMatrix bitMatrix = qrCodeWriter.encode(qrCodeText, BarcodeFormat.QR_CODE, width, height);// 将BitMatrix转换为BufferedImageBufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);// 保存二维码图片到本地文件//File file = new File("D:\\图片\\qrcode.png");//ImageIO.write(bufferedImage, format, file);//log.info("QR Code image generated successfully!");// 生成二维码图像ByteArrayOutputStream outputStream = new ByteArrayOutputStream();MatrixToImageWriter.writeToStream(bitMatrix, "png", outputStream);// 获取图像的字节数组,并使用 Base64 编码转换成字符串byte[] imageData = outputStream.toByteArray();base64Image = AppConfigUtil.getStringValue(TwoFactorAuthConstant.MICROSOFT_AUTH_BASE64_IMAGE) + java.util.Base64.getEncoder().encodeToString(imageData);return base64Image;} catch (WriterException e) {throw new BusinessException(I18nMsg.tr("生成二维码图像失败"));} catch (Exception e) {throw new BusinessException("Unexpected error:" + e.getMessage());}} catch (BusinessException e) {throw new BusinessException(I18nMsg.tr("生成二维码发生异常:{0}", e.getMessage()));}}
}

二次验证的接口:

public interface TwoFactorAuthProvider {//生成密钥String getSecretKey();//校验密钥boolean checkCode(String secret, long code, long time);
}

实现类代码如下:

@Service
public class MicrosoftAuth implements TwoFactorAuthProvider {// 私有构造方法private MicrosoftAuth() {}// 在成员位置创建该类的对象private static MicrosoftAuth microsoftAuth;// 对外提供静态方法获取该对象public static synchronized MicrosoftAuth getMicrosoftAuth() {if (microsoftAuth == null) {microsoftAuth = new MicrosoftAuth();}return microsoftAuth;}/*** 时间前后偏移量* 用于防止客户端时间不精确导致生成的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 int WINDOW_SIZE = 1;/*** 加密方式,HmacSHA1、HmacSHA256、HmacSHA512*/private static final String CRYPTO = "HmacSHA1";/*** description: 生成密钥,每个用户独享一份密钥** @return java.lang.String* @author litong* @date 2023/4/27*/@Overridepublic String getSecretKey() {String secretKey = null;try {SecureRandom random = new SecureRandom();byte[] bytes = new byte[20];random.nextBytes(bytes);Base32 base32 = new Base32();secretKey = base32.encodeToString(bytes).toUpperCase();} catch (Exception e) {throw new BusinessException(I18nMsg.tr("生成密钥发生异常:{0}", e.getMessage()));}// make the secret key more human-readable by lower-casing and// inserting spaces between each group of 4 charactersreturn secretKey;}/*** 检验 code 是否正确** @param secret 密钥* @param code   code* @param time   时间戳* @return*/@Overridepublic boolean checkCode(String secret, long code, long time) {boolean flag = false;try {Base32 codec = new Base32();byte[] decodedKey = codec.decode(secret);// convert unix msec time into a 30 second "window"// this is per the TOTP spec (see the RFC for details)long t = (time / 1000L) / 30L;// Window is used to check codes generated in the near past.// You can use this value to tune how far you're willing to go.long hash;for (int i = -WINDOW_SIZE; i <= WINDOW_SIZE; ++i) {try {hash = verifyCode(decodedKey, t + i);} catch (Exception e) {// Yes, this is bad form - but// the exceptions thrown would be rare and a static// configuration problem// e.printStackTrace();throw new RuntimeException(e.getMessage());}if (hash == code) {flag = true;return flag;}}} catch (RuntimeException e) {throw new BusinessException(I18nMsg.tr("校验密钥发生异常:{0}", e.getMessage()));}return flag;}/*** 根据时间偏移量计算** @param key* @param t* @return* @throws NoSuchAlgorithmException* @throws InvalidKeyException*/private static long verifyCode(byte[] key, long t) throws NoSuchAlgorithmException, InvalidKeyException {try {byte[] data = new byte[8];long value = t;for (int i = 8; i-- > 0; value >>>= 8) {data[i] = (byte) value;}SecretKeySpec signKey = new SecretKeySpec(key, CRYPTO);Mac mac = Mac.getInstance(CRYPTO);mac.init(signKey);byte[] hash = mac.doFinal(data);int offset = hash[20 - 1] & 0xF;// We're using a long because Java hasn't got unsigned int.long truncatedHash = 0;for (int i = 0; i < 4; ++i) {truncatedHash <<= 8;// We are dealing with signed bytes:// we just keep the first byte.truncatedHash |= (hash[offset + i] & 0xFF);}truncatedHash &= 0x7FFFFFFF;truncatedHash %= 1000000;return truncatedHash;} catch (NoSuchAlgorithmException | InvalidKeyException | IllegalStateException e) {throw new BusinessException(I18nMsg.tr("生成系统验证密钥出现异常{0}",e.getMessage()));}}
}

简单应用到系统中的步骤如下:

1.定义工具类和实现类

2.编写获取用户名密钥的接口,生成的密钥做持久化

3.使用工具类将密钥和用户名生成二维码,返回给前端,显示大概如下:

4.使用二次验证APP扫描二维码进行绑定,软件会自动生成验证码

5.前端传递对应的验证码到后端,后端使用工具类中的方法校验,返回值为boolean类型

这样系统就将微软二次验证系统接入到你的系统里面啦

使用Microsoft-Authenticator做系统登录的二次验证相关推荐

  1. Centos7机器配置Google Authenticator动态密钥进行ssh二次验证图文详解

    就跟银行账户登录需要手机短信或者令牌进行二次验证一样,给企业的业务电脑配置远程ssh登录的二次验证也是一个非常必要的安全措施,这样即使坏人知道了访问密码也无法登录机器.这篇文章就记录下今天我给一台机器 ...

  2. 亚马逊卖家账号多人免登录免二次验证,买家号Cookies批量登录,cookie管理,亚马逊Cookie账号怎么导入导出

    相关搜索: 浏览器限制了第三方cookie 浏览器禁用cookie什么意思 请保证浏览器没有禁用cookie 浏览器的cookies在哪里打开 cookie怎么获得 网页cookie 如何启用cook ...

  3. 计算机操做系统(十二):进程同步和互斥

    计算机操做系统(十二):进程同步和互斥 来源王道考研视频: https://www.bilibili.com/video/BV1YE411D7nH?p=18 基本概念 异步性:各并发执行的进程以各自独 ...

  4. Microsoft365账号登录安全保护:使用microsoft authenticator应用验证

    国际版Microsoft365在web端登录后显示组织需要更多信息,来保护账号安全. 点击下一步 使用Microsoft authenticator进行验证,在手机中下载authenticator客户 ...

  5. 在你的计算机上使用qr码登录,如何设置和使用Microsoft Authenticator Qr代码

    Microsoft Authenticator是一个帐户验证应用程序,可让您以更高的安全性登录Microsoft帐户,同时非常易于使用. 这些天我们不得不为不同的应用程序,设备和网站处理这么多不同的密 ...

  6. 广西外国语学院计算机二级,广西外国语学院教务系统登录入口民办二本学小语种比较有前途...

    广西外国语学院坐落在广西壮族自治区首府--南宁,是一所经教育部批准成立的全日制民办本科学校,前身是广西东方外语职业学院.根据调查,百分之80的人认为还不错,还不错,校园占地很大,环境优美!离市中心不算 ...

  7. 12306抢票系统(登录功能---二维码+账号密码)

    文章目录 一.二维码登录方式 二.账号密码登录方式 超级鹰第三方库 账号密码登录 代码汇总: 一.二维码登录方式 二维码登录方式:用户手机端扫描网页二维码登录,比账号密码登录更简易 话不多说,先上代码 ...

  8. Linux下使用Google Authenticator配置SSH登录动态验证码

    说明: 1.一般ssh登录服务器,只需要输入账号和密码. 2.本教程的目的:在账号和密码之间再增加一个 验证码,只有输入正确的验证码之后,再输入 密码才能登录.这样就增强了ssh登录的安全性. 3.账 ...

  9. 破解Visra系统登录密码

    微软苦心"打磨"了五年的操作系统,一再宣称是"史上最安全"的Windows Vista竟然是如此的脆弱,系统登录密码竟然是形同虚设!不论是谁,只要拥有一张Vis ...

最新文章

  1. java urlstreamhandler_获取对Java的默认http(s)URLStreamHandler的引用
  2. openStack 云平台管理节点管理网口流量非常大 出现丢包严重 终端总是时常中断问题调试及当前测试较有效方案...
  3. hihoCoder#1037 : 数字三角形(DP)
  4. Mybatis-plus多表关联查询,多表分页查询
  5. 【STM32】typedef 类型及配合结构体使用
  6. 虚函数练习:交通工具信息
  7. 网络编程懒人入门(六):史上最通俗的集线器、交换机、路由器功能原理入门
  8. 反射setaccessible_advancedday16类加载器,反射
  9. oracle中时间加减一年的写法
  10. Java提高篇 —— String缓冲池
  11. 大厂在用的Python反爬虫手段,破了它!
  12. Python学习笔记之While循环(二)
  13. Oracle字符集的设置
  14. linux java运行环境_linux(centos)中java运行环境_jdk安装与配置 | OPS技术联盟
  15. 吸猫就吸Tomcat之Pipeline-Valve巧妙设计
  16. 辗转相减法的发展应用-最大比例
  17. 【数字信号处理】基于matlab GUI数字信号处理系统【含Matlab源码 1088期】
  18. mysql 与紫金桥_组态软件的国内品牌
  19. TD-SCDMA正传(1)
  20. Chromium Embedded Framework (CEF) 介绍

热门文章

  1. 浅析在航空航天型号研制项目管理中进度计划管理的应用
  2. 帝国cms手机和pc站数据同步建站教程
  3. 武林外传显示服务器连接失败,武林外传手游服务器链接失败怎么回事_武林外传手游服务器链接失败如何解决_玩游戏网...
  4. 不同钣金展开方法对比研究与应用
  5. web页面播放语音提示保存成功
  6. 利用浏览器F12排查前端(JSP)页面错误
  7. Codeforces 1169B Pairs
  8. 小谈Springcloud中的几个主流熔断器
  9. 新手怎么开始学习3Dmax?学习MAX的七个建议,不再迷茫!
  10. Android实现卡拉OK字幕效果方法