在nodejs中实现双重身份验证机制

news2025/3/13 15:20:33

在nodejs中实现双重身份验证机制

在这里插入图片描述

双重身份验证(Two-factor authentication)是一种安全机制,它要求用户提供两种不同的身份验证因素来访问他们的帐户:密码和发送到他们的移动设备的验证码。在本文中,我们将一步步通过使用speakeasynodejs中实现双重身份验证。

步骤1

首先安装依赖项,我们需要安装expressspeakeasy

npm install express speakeasy

步骤2

创建一个express服务,并将其配置使用JSON中间件和静态资源中间件:

const express = require('express');
const app = express();

app.use(express.json());
app.use(express.static('public'));
app.listen(3000, () => {
  console.log('Server started on port 3000');
});

步骤3

创建一个用户模型User,用于在数据库中存储用户数据。在这个例子中,我们将使用一个简单的数组来存储用户数据:

const users = [];

class User {
  constructor(id, name, email, password, secret) {
    this.id = id;
    this.name = name;
    this.email = email;
    this.password = password;
    this.secret = secret;
  }
}
module.exports = { users, User };

步骤4

创建一个POST请求的路由用于处理用户的注册操作。在此路由中,我们将为用户生成一个密钥并将其保存在数据库中。我们还会向用户发送一个二维码,用户可以扫描这些代码,以便将帐户添加到他们的应用程序中:

const { users, User } = require('./user');
const speakeasy = require('speakeasy');
const QRCode = require('qrcode');

app.post('/register', (req, res) => {
  const { name, email, password } = req.body;
  // 为用户生成新的密钥
  const secret = speakeasy.generateSecret({ length: 20 });
  // 保存用户数据
  const user = new User(users.length + 1, name, email, password, secret.base32);
  users.push(user);
  // 生成一个二维码供用户扫描
  QRCode.toDataURL(secret.otpauth_url, (err, image_data) => {
    if (err) {
      console.error(err);
      return res.status(500).send('Internal Server Error');
    }
    res.send({ qrCode: image_data });
  });
});

步骤5

创建一个POST请求的路由用于处理用户的登录操作。在此请求中,我们将验证用户的凭证,并需要从用户的应用程序中获得验证码。我们将使用speakeasy来生成和验证这个验证码:

const { users } = require('./user');
const speakeasy = require('speakeasy');

app.post('/login', (req, res) => {
  const { email, password, token } = req.body;
  const user = users.find(u => u.email === email);
  // 验证用户的凭证
  if (!user || user.password !== password) {
    return res.status(401).send('Invalid credentials');
  }
  // 核实用户的令牌
  const verified = speakeasy.totp.verify({
    secret: user.secret,
    encoding: 'base32',
    token,
    window: 1
  });
  if (!verified) {
    return res.status(401).send('Invalid token');
  }
  // 用户经过认证
  res.send('Login successful');
});

我们通过检查用户是否存在以及他们的密码是否与请求中提供的密码匹配来验证用户的凭证。

如果用户的凭证有效,我们使用speakeasy 来验证二维码。我们传递用户的密钥编码(应该是base32 )、请求中提供的令牌和window: 1(代表令牌在当前和前一个时间段有效)。

如果令牌无效,我们将返回一个401未经授权的状态码,其中包含消息"无效令牌"。

如果令牌有效,我们将发送一个200OK的状态码,其中包含"成功登录"的消息。此时,用户将进行身份验证,并可以访问应用程序中受保护的资源。

步骤6

创建一个中间件来验证用户是否已经成功登录。

const speakeasy = require('speakeasy');

exports.requireToken = (req, res, next) => {
  const { token } = req.body;
  // Find the user with the given email address
  const user = users.find(u => u.email === req.user.email);
  // Verify the user's token
  const verified = speakeasy.totp.verify({
    secret: user.secret,
    encoding: 'base32',
    token,
    window: 1
  });
  if (!verified) {
    return res.status(401).send('Invalid token');
  }
  // 令牌有效,继续到下一个中间件或路由处理程序
  next();
}

下面这个路由中添加了requireToken中间件,需要存在一个有效的2FA令牌才能继续使用:

app.post('/protected', requireToken, (req, res) => {
  // 只有当用户的令牌有效时才会调用此路由处理程序
  res.send('Protected resource accessed successfully');
});

总之,双重身份验证机制(2FA)是一种强大的安全机制,它为用户帐户增加了额外的保护层。通过要求用户提供两个不同的身份验证因素,例如密码和发送到他们的移动设备的代码,2FA可以帮助防止未经授权访问敏感信息。

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

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

相关文章

deforum + kandinsky = 视频工作流

像搭积木一样玩AI,随着模型种类的不断丰富,不同的组合会带来什么惊喜?今天和大家分享最近看到的一个视频工作流(工具箱)。 首先,我们先对deforum和kandinsky做一些基本的介绍: deforum-art/defo…

【论文解读】单目3D目标检测 CUPNet(ICCV 2021)

本文分享单目3D目标检测,CUPNet 模型的论文解读,了解它的设计思路,论文核心观点,模型结构,以及效果和性能。 目录 一、CUPNet简介 二、论文核心观点 三、模型框架 四、损失函数 五、核心观点——3D高度估计误差 引…

Python之并发编程(进程)

文章目录 一、操作系统的发展史二、进程基础(操作系统中的概念)1.什么是进程2.进程的调度算法3.进程的并行与并发4.进程的三状态5.同步异步6.阻塞与非阻塞7.同步异步与阻塞非阻塞综合使用 三、如何创建进程Process的几个方法如何开启多进程进程间的数据默认隔离基于TCP协议的高…

【Qt控件之QButtonGroup】概述及使用

概述 QButtonGroup 类提供了一个容器来组织一组按钮部件。 QButtonGroup 提供了一个抽象容器,可以将按钮部件放置其中。它不提供此容器的可视表示(请参见 QGroupBox,用于容器部件),而是管理组中每个按钮的状态。 一个…

Electron webview 内网页 与 preload、 渲染进程、主进程的常规通信 以及企业级开发终极简化通信方式汇总

Electron 嵌入的页面中注入的是 preload.js 通过在标签中给 prelaod赋值,这里提到了 file://前缀,以及静态目录 static 怎么获取 实际代码,其中__static就是我们存放静态文件的地方,这个 static 是 electron 源代码根目录下的文件…

使用unordered_write调优RocksDB写性能

在使用rocksdb存储的服务中,我们发现QPS在4w/s就怎么调整都上不去了,写性能受到了某种限制。为什么呢?下图描述了rocksdb写入的流程。我们发现 unordered_write true可以提高写入吞吐量。 rocksdb的数据正常写入流程是,多个线程形…

九月 NFT 行业解读:熊市情绪仍占上风

作者: stellafootprint.network 9 月,著名主流媒体《滚石》(Rolling Stone)发表了一篇题为《你的 NFT 实际上——终于——完全不值钱了》(Your NFTs Are Actually — Finally — Totally Worthless)的文章&#xff0c…

【网络编程】从网络编程、TCP/IP开始到BIO、NIO入门知识(未完待续...)

目录 前言前置知识一、计算机网络体系结构二、TCP/IP协议族2.1 简介*2.2 TCP/IP网络传输中的数据2.3 地址和端口号2.4 小总结 三、TCP/UDP特性3.1 TCP特性TCP 3次握手TCP 4次挥手TCP头部结构体 3.2 UDP特性 四、总结 课程内容一、网络通信编程基础知识1.1 什么是Socket1.2 长连…

NumPy基础及取值操作

目录 第1关:ndarray对象 相关知识 怎样安装NumPy 什么是ndarray对象 如何实例化ndarray对象 使用array函数实例化ndarray对象 使用zeros,ones,empty函数实例化ndarray对象 代码文件 第2关:形状操作 相关知识 怎样改变n…

液压自动化成套设备比例阀放大器

液压电气成套设备的比例阀放大器是一种电子控制设备,用于控制液压动力系统中的液压比例阀1。 比例阀放大器通常采用电子信号进行控制,以控制比例阀的开度和流量,以实现液压系统的可靠控制。比例阀放大器主要由以下组成部分: 驱动…

tomcat 服务器

tomcat 服务器 tomcat: 是一个开源的web应用服务器。区别nginx,nginx主要处理静态页面,那么动态请求(连接数据库,动态页面)并不是nginx的长处,动态的请求会交给tomcat进行处理。 nginx-----转发动态请求-…

Golang学习:基础知识篇(三)—— Map(集合)

Golang学习:基础知识篇(三)—— Map集合 前言什么是Golang?Map集合定义 Map综合实例补充 前言 很久之前就想学Go语言了,但是一直有其他东西要学,因为我学的是Java嘛,所以后面学的东西一直是跟J…

Element-UI 日期选择器--禁用未来日期

在做项目的时候经常会遇到一些报表需要填写日期,一般是填写当日及当日以前,这时候我们的日期选择器就需要进行一些限制,比如: 这样之后,就不会误填写到明天啦,下面让我们看一下代码实现 html页面代码 这里…

Unity ECS最新DOTS环境搭建教程

最近DOTS终于发布了正式的版本, 今天我们来基于Unity 2023.1.6来搭建DOTS 1.0.16的开发环境与注意事项。 对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正在从事游戏开发的技术大佬,欢迎你来交流学习。 1…

Liunx C运算符

一、运算符 &#xff08;一&#xff09;算数运算符 1、float和double不能进行取余操作。 &#xff08;二&#xff09;关系运算符 1、逻辑非 2、逻辑与 例子&#xff1a; if(&#xff08;a-1&#xff09;<b&&b) 如果为真则自增&#xff0c;为假不自增 3、逻辑或 …

leaflet 绘制显示半圆形,扇形示例 (134)

第134个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中绘制显示半圆形,扇形 。这里引用了一个插件,非常方便的绘制扇形和半圆形等。 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共77行)安装插件相…

虚拟内存技术的基本概念(局部性原理,特征,实现)

1.传统存储管理方式的特征、缺点 很多暂时用不到的数据也会长期占用内存&#xff0c;导致内存利用率不高。 1.一次性: 作业必须一次性全部装入内存后才能开始运行。 这会造成两个问题: ①作业很大时&#xff0c;不能全部装入内存&#xff0c;导致大作业无法运行; ②当大量作…

node多版本管理器nvm

node多版本管理器nvm 1、为何要使用node版本管理器2、nvm安装步骤2-1、卸载系统中的node2-2、下载nvm2-3、安装 3、维护node版本3-1、安装指定版本node3-2、查看本机已安装的所有node版本3-3、切换本机node版本 1、为何要使用node版本管理器 在日常开发中&#xff0c;难免会遇…

apache log4j漏洞复现

log4j是开源的java存储日志的框架&#xff0c;一般都是大企业用&#xff0c;小企业自带的日志功能足够使用&#xff0c;Log4j2是默认支持解析ldap/rmi协议的&#xff0c;打印的日志中包括ldap/rmi协议都行。 具体介绍参考以下文章&#xff1a; log4j2---基于vulhub的log4j2漏…

Triple协议的隐式参数传递过程

前言 Dubbo 框架的 RPC 调用除了可以传递正常的接口参数外&#xff0c;还支持隐式参数传递。 隐式参数的传递依赖 RpcContext 对象&#xff0c;它持有一个 Map 对象&#xff0c;消费者往 Map 里写入数据&#xff0c;客户端在发起 RPC 调用前会构建 RpcInvocation&#xff0c;然…