当前位置: 首页 > news >正文

node中使用jsonwebtoken实现身份认证

在现代web应用中,用户身份认证是非常重要且必不可少的一环。而使用Node.jsExpress框架,可以方便地实现用户身份认证。而在这个过程中,jsonwebtoken这个基于JWT协议的模块可以帮助我们实现安全且可靠的身份认证机制,可以让我们轻松地生成、解析和验证JWT。本文主要介绍如何在Node.jsExpress框架中使用jsonwebtoken模块来实现用户身份认证。

一、什么是jwt

jwt介绍:https://restfulapi.cn/jwt

JWTJSON Web Token)是一种基于JSON的开放标准,用于在网络上以安全方式传输声明JWT通常用于身份验证和授权。它是一种可自包含的身份认证机制,由三部分组成头部、载荷和签名JWT的头部和载荷都是使用Base64编码后的JSON字符串,签名是由头部和载荷使用密钥进行哈希计算得到的字符串。JWT可以在客户端和服务器之间传输,并且可以在传输过程中防止数据被篡改。由于它是无状态的,因此可以简化Web应用程序的开发和维护。
在这里插入图片描述

二、jsonwebtoken基本使用

jsonwebtoken是一个Node.js库,用于创建、解码和验证JWT令牌(JSON Web Tokens)。在Web应用中,这些令牌通常用于身份验证和授权

以下是如何在Node.js应用中使用jsonwebtoken基本步骤

1. 安装jsonwebtoken

首先,你需要使用npm或yarn将jsonwebtoken包添加到你的项目中:

npm install jsonwebtoken --save

或者

yarn add jsonwebtoken

2. 导入使用

然后,在你的代码中导入jsonwebtoken:

const jwt = require('jsonwebtoken');

3. 创建token

创建一个令牌:

let token = jwt.sign({ foo: 'bar' }, 'shhhhh');

在上面的代码中,我们使用jwt.sign方法创建了一个新的令牌。
这个方法需要两个参数

  • 一个包含你的payload的对象(这个对象中的数据会被编码到生成的令牌中)比如:userInfo
  • 用来签名令牌的秘密字符串

4. 验证token

验证一个令牌:

jwt.verify(token, 'shhhhh', (err, decoded) => {if (err) {// 处理错误} else {// 使用解码后的令牌数据}
});

使用jwt.verify方法可以解码并验证一个令牌。

该方法需要三个参数

  • 解码的令牌
  • 用于签名的相同的秘密字符串
  • 操作完成时被调用的回调函数

注意

  • 所有的令牌都应该只通过HTTPS发送,以防止被拦截。

  • 秘密字符串应该在你的应用中保持私密,不能让其他人知道。

  • 任何存储在令牌中的信息都可以被任何拥有秘密的人解码。因此,你永远不应该在令牌中存储敏感信息(如密码或银行账户信息)

三、在express中应用示例

在实际项目中,我们可以使用jsonwebtoken模块来实现身份认证。jsonwebtoken是基于JSON Web Tokens(JWT)协议的实现模块,可以用于生成、解析和验证JWTJWT是一种基于JSON的开放标准(RFC 7519),用于在网络上安全地传输声明。

以下是一个使用expressjsonwebtoken实现身份认证的示例:

const express = require('express');
const jwt = require('jsonwebtoken');const app = express();// 定义一个中间件函数,用于身份认证
function verifyToken(req, res, next) {// 从请求头中获取tokenconst token = req.headers['authorization'];if (!token) {return res.status(401).send({auth: false,message: 'No token provided.'});}// 验证token是否有效jwt.verify(token, process.env.SECRET_KEY, (err, decoded) => {if (err) {return res.status(500).send({auth: false,message: 'Failed to authenticate token.'});}// 将解码的用户信息存储到请求对象中req.userId = decoded.id;next();});
}// 定义一个路由,需要身份认证
app.get('/api/protected', verifyToken, (req, res, next) => {// 返回受保护的数据res.status(200).send({message: 'Access granted.'});
});// 定义一个路由,用于登录,返回token
app.post('/api/login', (req, res, next) => {// 从数据库中获取用户信息const user = { id: 123 };// 生成tokenconst token = jwt.sign({ id: user.id }, process.env.SECRET_KEY, {expiresIn: 60 * 60 // token有效期为1小时});// 返回tokenres.status(200).send({auth: true,token: token});
});// 启动服务器,监听端口
app.listen(3000, () => {console.log('Server started on port 3000');
});

在上述示例中,我们定义了一个中间件函数verifyToken用于身份认证。该函数从请求头中获取token,并通过jsonwebtoken的verify方法验证token是否有效。如果验证通过,则将用户信息存储到请求对象中,以便后续路由函数使用。

我们还定义了两个路由函数,/api/protected/api/login/api/protected需要身份认证才能访问,而/api/login用于登录,并返回生成的token

在实际项目中,我们应该将SECRET_KEY等敏感信息放在环境变量中,以提高安全性。此外,我们还可以使用jsonwebtoken提供的其他功能,如验证token的签名算法、payloadheader等信息。

四、jwt逻辑抽离

在上面的示例中我们用jwt实现了身份认证,但是这只是在一个接口中认证,如果接口多了呢,每次都要将这个认证的中间件加上吗?这样先不说开发实现的累不累,冗余不,单从维护层面来讲,也是很不合理。所以我们应该将认证的逻辑抽离出来,以便于接口调用和维护。具体步骤如下:

1. 新建jwt.js文件

这个文件中就封装三个函数

  • token的生成
  • token的认证
  • 排除哪些接口不需要认证就可以访问,比如/login,
// jwt.js
const jwt = require("jsonwebtoken");
const { promisify } = require("util");
const { uuid } = require("../config/config.default");
const tojwt = promisify(jwt.sign);
const verfiy = promisify(jwt.verify);// 生成token
module.exports.createToken = async (userinfo) => {var token = await tojwt({ userinfo }, uuid, {expiresIn: 60 * 60 * 24,});return token;
};// jwt认证的中间件
const jwtAuthMiddleware = async (req, res, next) => {var token = req.headers.authorization;token = token ? token.split("Bearer ")[1] : null;if (!token) {return res.status(402).json({ error: "请传入token" });}if (token) {try {let userinfo = await verfiy(token, uuid);req.user = userinfo;next();} catch (error) {res.status("402").json({ error: "无效的token" });}} else {next();}
};// 承认的url排除列表
const jwtAuthExcluedList = ['/api/login', '/api/register'];
// 检查排除列表的中间件
module.exports.jwtAuthExclued = (req, res, next) => {// 检查请求 URL 是否在排除 jwtAuth 的列表里面if (jwtAuthExcluedList.includes(req.path)){next(); // 在列表里,跳过后续中间件} else { jwtAuthMiddleware(req, res, next); // 不在列表里,就调用jwt中间件进行身份认证}
};

这样封装以后,我们只需要在访问路由之前,添加使用jwtAuthExclued 的中间件就可以实现对接口的token认证,在login接口中调用createToken生成token可以了。

2. 在登录接口中生成token

比如:

  • loginController
// login
// 用户登录
exports.login = async (req, res) => {// 客户端数据验证// 链接数据库查询var dbBack = await User.findOne(req.body)if (!dbBack) {return res.status(402).json({ error: "邮箱或者密码不正确" })}dbBack = dbBack.toJSON()dbBack.token = await createToken(dbBack)res.status(200).json(dbBack)
}

3. 添加全局认证中间件

  • app.js
const express = require("express");
const app = express();
const { jwtAuthExclued } = require("./util/jwt");
const router = require("./router");// 添加排除jwt中间件
app.use(jwtAuthExclued); 
// 添加路由中间件
app.use('/api', router);

五、jwt和session对比

下面是JWTSession的对比表格:

对比因素JWTSession
存储存储在客户端,不需要服务器保持会话状态。存储在服务器,需要服务器维护会话信息。
安全性加密较严密,但如果token被窃取,攻击者可以任意使用。如果sessionID被窃取,攻击者可以冒充用户登陆。
性能在每次请求时需要验证和解码token,性能较差。只需查找sessionID就能获取会话信息,性能较好。
扩展性在多服务器或者跨域环境中更易扩展。在多服务器环境中需要同步session,扩展性较差。
数据大小JWT的大小比sessionID大,因此需要更多的带宽。sessionID大小稳定,对带宽需求较小。
到期时间可以为每个token设置不同的过期时间。所有session的过期时间通常相同。
客户端存储位置可以存储在Cookie, LocalStorage, SessionStorage中存储在Cookie中。
跨域问题无跨域问题,且对于移动应用而言友好。跨域问题复杂,需要服务器支持CORS。
状态无状态,服务器不需要保存用户信息。有状态,服务器需要保存用户信息。
使用场景用于认证和信息交换,尤其适合单页应用(SPA)和前后端分离的项目主要用于记录用户状态,适配传统的后端渲染的Web服务

总体上来说,JWT适用于前后端分离的API服务,它可以简化服务端的存储需求,并提供更好的跨平台兼容性和可扩展性,同时也能提供安全可靠的身份认证机制。而Session适用于服务器渲染的Web应用,它可以提供更高的安全性和可调用性,同时也能减轻客户端的流量负担。不同的场景需要选择最适合的身份认证方案,根据实际需求进行选择。

六、总结

在本文中,我们探讨了如何在Node.jsExpress框架中使用jsonwebtoken来实现身份认证。我们首先介绍了JWT协议和jsonwebtoken模块的基础知识,然后展示了如何在Express中使用jsonwebtoken来生成、解析和验证JWT。通过在实际项目中的举例,我们演示了如何将jsonwebtoken与路由中间件结合使用,实现基于token的用户身份认证机制。使用jsonwebtoken可以为我们的web应用提供更安全和可靠的用户身份认证方案,同时jwt的优点也是很明显的:无需在服务端保存session信息,具有可扩展性和跨平台兼容性等特点。通过本文的介绍,相信读者已经能够掌握jsonwebtoken的基本使用方法和原理,能够在实际项目中使用jsonwebtoken实现安全可靠的身份认证机制。

相关文章:

node中使用jsonwebtoken实现身份认证

在现代web应用中,用户身份认证是非常重要且必不可少的一环。而使用Node.js和Express框架,可以方便地实现用户身份认证。而在这个过程中,jsonwebtoken这个基于JWT协议的模块可以帮助我们实现安全且可靠的身份认证机制,可以让我们轻…...

pyspark笔记:读取 处理csv文件

pyspark cmd上的命令 1 读取文件 1.1 基本读取方式 注意读取出来的格式是Pyspark DataFrame,不是DataFrame,所以一些操作上是有区别的 1.1.1 format DataFrame spark.read.format("csv").option(name,value).load(path) format表示读取…...

多租户分缓存处理

多租户redis缓存分租户处理 那么数据库方面已经做到了拦截,但是缓存还是没有分租户,还是通通一个文件夹里, 想实现上图效果,global文件夹里存的是公共缓存。 首先,那么就要规定一个俗称,缓存名字带有globa…...

RN输入框默认设置数字键盘

<TextInput keyboardType"numeric"/> keyboardType 决定弹出何种软键盘类型&#xff0c;譬如numeric&#xff08;纯数字键盘&#xff09;。 See screenshots of all the types here. 这些值在所有平台都可用&#xff1a; defaultnumber-paddecimal-padnume…...

计算机网络——应用层

文章目录 **1 网络应用模型****2 域名系统DNS****3 文件传输协议FTP****4 电子邮件****4.1 电子邮件系统的组成结构****4.2 电子邮件格式与MIME****4.3 SMTP和POP3** **5 万维网WWW****5.1 HTTP** 1 网络应用模型 客户/服务器模型 C/S 服务器服务于许多来自其他称为客户机的主…...

【C++】写一个函数实现系统时间与输入时间进行比较

目录 1 代码 2 运行结果 时间比较函数: 输入为字符串2023-7-28,将字符串分解为年、月、日信息。 获取系统时间2023-7-24,然后将输入时间和系统时间进行比较,输出比较结果。 1 代码 #include <ctime> #include<iostream> #include<vector> using names…...

uniapp 微信小程序 navigationBarBackgroundColor 标题栏颜色渐变

大体思路&#xff1a; 第一步&#xff1a;“navigationStyle”:“custom” 第二步&#xff1a; template内 重点&#xff1a;给view添加ref“top” 第三步&#xff1a;添加渐变色样式 1、pages.json {"path" : "pages/user/user","style" : …...

ffplay播放器剖析(7)----音视频暂停模块分析

文章目录 1. 暂停触发流程2. toggle_pause3. stream_toggle_pause 1. 暂停触发流程 1.通过SDL触发事件调用toggle_pause 2.toggle_pause调用stream_toggle_pause 3.stream_toggle_pause修改暂停变量 2. toggle_pause static void toggle_pause(VideoState *is) {stream_to…...

ceph-mon运行原理分析

一、流程&#xff1a;ceph-deploy部署ceph-mon组建集群 1.ceph-deploy部署ceph-mon的工作流程及首次启动 1&#xff09;通过命令创建ceph-mon&#xff0c;命令为&#xff1a;ceph-deploy create mon keyring def mon(args):if args.subcommand create:mon_create(args)elif…...

听GPT 讲K8s源代码--pkg(八)

k8s项目中 pkg/kubelet/envvars&#xff0c;pkg/kubelet/events&#xff0c;pkg/kubelet/eviction&#xff0c;pkg/kubelet/images&#xff0c;pkg/kubelet/kubeletconfig这些目录都是 kubelet 组件的不同功能模块所在的代码目录。 pkg/kubelet/envvars 目录中包含了与容器运行…...

差速驱动机器人的车轮里程计模型

一、说明 车轮测程法是指使用旋转编码器(即连接到车轮电机以测量旋转的传感器)的测程法(即估计运动和位置)。这是轮式机器人和自动驾驶汽车定位的有用技术。 在本文中,我们将通过探索差速驱动机器人的车轮里程计模型来深入研究车轮里...

Pytorch个人学习记录总结 09

目录 损失函数与反向传播 L1Loss MSELOSS CrossEntropyLoss 损失函数与反向传播 所需的Loss计算函数都在torch.nn的LossFunctions中&#xff0c;官方网址是&#xff1a;torch.nn — PyTorch 2.0 documentation。举例了L1Loss、MSELoss、CrossEntropyLoss。 在这些Loss函数…...

代码随想录算法训练营day51 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费

题目链接309.最佳买卖股票时机含冷冻期 class Solution {public int maxProfit(int[] prices) {if (prices null || prices.length < 2) {return 0;}int[][] dp new int[prices.length][2];dp[0][0] -prices[0];dp[0][1] 0;dp[1][0] Math.max(dp[0][0], dp[0][1] - pr…...

做UI设计需要具备什么平面技能呢优漫动游

想要成为一名合格的UI设计师&#xff0c;那么需要学会的技能是非常多的&#xff0c;UI设计包含的知识点也比较多&#xff0c;那么具体做UI设计需要具备什么技能呢?来看看下面小编的详细介绍吧。 —、软件能力 一位好的ui设计师除了需要精通Photoshop.IlustratorDW.C4D等设…...

cass--单选不累加设置

打开软件&#xff0c;在空白处右击--选项--选择&#xff0c;如下&#xff1a; 完成后&#xff0c;点击确定按钮即可。...

线程结构——链表

C中的链表是一种非常常见的数据结构&#xff0c;它由一系列节点组成&#xff0c;每个节点包含一个数据元素和一个指向下一个节点的指针。 链表结构包括单向链表、双向链表和循环链表&#xff1b; 1.单向链表 单向链表由一系列节点组成&#xff0c;每个节点包含一个数据元素和…...

freeRTOS:基于(信号量+线程)的日志系统设计

1.日志的重要性 故障排查与调试&#xff1a;嵌入式系统通常运行在资源有限的环境中&#xff0c;故障排查和调试变得尤为复杂。日志系统可以记录系统在运行过程中的各种操作、状态和事件信息&#xff0c;方便开发人员追踪和定位问题所在。通过分析日志&#xff0c;可以快速找到故…...

数据可视化(1)

使用python带的matplotlib库进行简单的绘图。使用之前先进行安装&#xff0c;pip install matplotlib。如果安装了Anaconda,则无需安装matplotlib。 1.简单折线图 #绘制简单图表 import matplotlib.pyplot as plt plt.plot([1,2,3,4,5]) plt.show() import matplotlib.pyp…...

Llama 2: Open Foundation and Fine-Tuned Chat Models

文章目录 TL;DRIntroduction背景本文方案 实现方式预训练预训练数据训练细节训练硬件支持预训练碳足迹 微调SFTSFT 训练细节 RLHF人类偏好数据收集奖励模型迭代式微调&#xff08;RLHF&#xff09;拒绝采样&#xff08;Rejection Sampling&#xff09;PPO多轮一致性的系统消息&…...

BTY-DNS AMA回顾:致力于创建Web3领域中的去中心化身份(DID)

传统域名系统 (DNS) 是一个分层的分散信息存储&#xff0c;用于将用户在网络浏览器中输入可读名称&#xff08;例如www.baidu.com&#xff09;解析为IP地址&#xff0c;来访问互联网上的计算机。传统域名系统存在一些例如过于集中化管理、效率并不高等局限性问题。而去中心化域…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

BLEU评分:机器翻译质量评估的黄金标准

BLEU评分&#xff1a;机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域&#xff0c;衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标&#xff0c;自2002年由IBM的Kishore Papineni等人提出以来&#xff0c;…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能

指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...