• Node中F2A原理及功能实现总结


    导语:之前做过一个小项目,其中用到了F2A(双因素认证)进行登录以及其他的用户身份认证,现在就这个功能的原理以及实现做一个总结。

    目录

    • F2A原理
    • 实现方法
    • 实战演练

    F2A原理

    F2A就是双因素认证的缩写,一种采用时间同步技术的系统,采用了基于时间、事件和密钥三变量而产生的一次性密码来代替传统的静态密码。

    大家都知道一般网站验证用户身份都是采用单因素认证,比如:用户名+密码,还有的是手机号+短信验证码。

    但是用户+密码的容易被黑客爆破,脱库,撞库进行获取;而短信验证码也容易被伪基站,钓鱼网站,WIFI等手段获取到,从而泄漏用户隐私信息。

    今天介绍的这个F2A就是在使用了上述提到的方法外,再另外加一层防护网,对用户登录进行二次验证,验证码是基于用户密钥独立生成的,随机生存的6位数。

    而且是在独立的APP专门设备上面存放,只有你自己可以查看,而且这个验证码是60秒切换一次,每次都不一样,加大了黑客破解的时间难度。

    实现方法

    继续打开上次的demo文件夹,然后创建一个f2a文件夹,写入一个文件index.js

    这次要实现的功能包括以下几点:

    • 生成二维码功能;
    • 生成F2A密钥
    • 验证F2A密码

    生成二维码功能

    这个功能比较简单,安装一个qrcode就可以了。

    $ npm install qrcode --save
    
    const express = require('express');
    const app = express();
    const qrcode = require('qrcode');
    
    app.get('/f2a/qrcode', (req, res) => {
        let url = req.query.url;
        if (!url) {
            return res.json({
                code: 101,
                msg: 'get_fail',
                data: {
                    info: "url不能为空!"
                }
            });
        }
        qrcode.toDataURL(url, (err, data) => {
            return res.send('<img src="' + data + '">');
        })
    })
    

    打开游览器,随便输入一个网址参数,来测试一下。

    这里使用百度一下:http://localhost:3000/f2a/qrcode?url=https://www.baidu.com/

    这里是预览截图:

    在这里插入图片描述

    生成F2A密钥

    接下来就是今天的主角登场,F2A双因素。

    先来下载一个依赖包,安装一下引入文件。

    $ npm install speakeasy --save
    

    获取F2A

    这里主要使用generateSecret来创建F2A密钥信息;

    const express = require('express');
    const app = express();
    const speakeasy = require('speakeasy');
    
    app.get('/f2a', (req, res) => {
        let secret = speakeasy.generateSecret({length: 20});
        return res.json({
            code: 200,
            msg: 'get_succ',
            data: {
                info: '获取成功',
                secret: secret.base32,
                url: secret.otpauth_url,
            }
        });
    })
    

    其中secret就是你的个人密钥,url就是你的F2A设备要扫描的地址。

    接下来在游览器看一下效果。

    在这里插入图片描述

    验证F2A密码

    这里主要使用totp.verify方法来验证六位数字是否为正确。

    app.post('/f2a', (req, res) => {
        let token = req.body.code;
        let secret = req.body.secret;
        if (!token) {
            return res.json({
                code: 101,
                msg: 'get_fail',
                data: {
                    info: "验证码不能为空!"
                }
            });
        }
        if (!(/^d{6}$/.test(token))) {
            return res.json({
                code: 101,
                msg: 'get_fail',
                data: {
                    info: "验证码格式不正确!"
                }
            });
        }
        if (!secret) {
            return res.json({
                code: 101,
                msg: 'get_fail',
                data: {
                    info: "密钥不能为空!"
                }
            });
        }
        let verifyInfo = {
            secret,
            encoding: 'base32',
            token,
        }
    
        let verify = speakeasy.totp.verify(verifyInfo);
        if (verify) {
            return res.json({
                code: 200,
                msg: 'get_succ',
                data: {
                    info: "验证成功!"
                }
            });
        } else {
            return res.json({
                code: 101,
                msg: 'get_fail',
                data: {
                    info: "验证失败!"
                }
            });
        }
    
    })
    

    其实这个依赖包还有个生成随机六位数的方法。

    app.get('/code', (req, res) => {
        let secret = req.query.secret;
        if (!secret) {
            return res.json({
                code: 101,
                msg: 'get_fail',
                data: {
                    info: "密钥不能为空!"
                }
            });
        }
    
        var token = speakeasy.totp({
            secret,
            encoding: 'base32'
        });
    
        return res.json({
            code: 200,
            msg: 'get_succ',
            data: {
                info: "获取成功!",
                code: token,
            }
        });
    
    })
    

    打开http://localhost:3000/f2a/code?secret=F44T62DGOJJT66TLH5WGWVBQJ47XUZJO,会出现一个六位数,这个就是生成的,大约有60秒有限期。

    在这里插入图片描述

    这个code里面的六位数其实和F2A应用的六位数是等效的,一样的,你也可以使用这个方法做一个类似的小程序,扫码绑定,显示六位数,这也是可以的。

    实战演练

    现在F2A的功能基本上是实现了,但是想要体验一下,你必须准备好F2A应用才可以。

    这里推荐三个比较常用F2A应用:

    在这里插入图片描述

    • 微信小程序:二次验证码

    在这里插入图片描述

    有了应用后,

    绑定F2A

    先打开那个网址,由于是get请求,直接在游览器打开,获取到密钥和地址。

    在这里插入图片描述

    现在已经出来了,

    • 密钥是secret的值:F44T62DGOJJT66TLH5WGWVBQJ47XUZJO,
    • 地址是url的值:otpauth://totp/SecretKey?secret=F44T62DGOJJT66TLH5WGWVBQJ47XUZJO

    接下来有两种方法绑定:

    • 直接在F2A应用输入secret里面;
    • 扫描二维码更方便(省去输入环节);

    接下来采用第二种方法。

    在游览器打开http://localhost:3000/f2a/qrcode?url=otpauth://totp/SecretKey?secret=F44T62DGOJJT66TLH5WGWVBQJ47XUZJO,看到一个二维码,使用F2A应用扫描后,成功绑定。

    在这里插入图片描述

    在这里插入图片描述

    F2A验证

    这次使用postman进行验证,打开postman软件,输入url以及参数。

    点击发送按钮,可以如下图,验证成功。

    在这里插入图片描述

    以上就是使用node实现F2A功能的一个基本的使用方法总结。

  • 相关阅读:
    c++ string 和wstring 之间的互相转换函数
    Duilib教程-自动布局3-分隔条
    Duilib教程-自动布局2
    Duilib教程-自动布局1
    Duilib教程-非DUI控件
    Duilib教程-控件练习
    Duilib教程-HelloDuilib及DuiDesigner的简单使用
    Duilib教程-简单介绍
    把資源加载到内存中 BMP 出错
    LoadLibrary失敗,GetLastError 返回127錯誤
  • 原文地址:https://www.cnblogs.com/guanqiweb/p/14968984.html
Copyright © 2020-2023  润新知