node中使用jsonwebtoken实现身份认证
在现代web应用中,用户身份认证是非常重要且必不可少的一环。而使用Node.js和Express框架,可以方便地实现用户身份认证。而在这个过程中,jsonwebtoken这个基于JWT协议的模块可以帮助我们实现安全且可靠的身份认证机制,可以让我们轻松地生成、解析和验证JWT。本文主要介绍如何在Node.js的Express框架中使用jsonwebtoken模块来实现用户身份认证。
一、什么是jwt
jwt介绍:https://restfulapi.cn/jwt
JWT(JSON 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)协议的实现模块,可以用于生成、解析和验证JWT。JWT是一种基于JSON的开放标准(RFC 7519),用于在网络上安全地传输声明。
以下是一个使用express和jsonwebtoken实现身份认证的示例:
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的签名算法、payload和header等信息。
四、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对比
下面是JWT和Session的对比表格:
| 对比因素 | JWT | Session |
|---|---|---|
| 存储 | 存储在客户端,不需要服务器保持会话状态。 | 存储在服务器,需要服务器维护会话信息。 |
| 安全性 | 加密较严密,但如果token被窃取,攻击者可以任意使用。 | 如果sessionID被窃取,攻击者可以冒充用户登陆。 |
| 性能 | 在每次请求时需要验证和解码token,性能较差。 | 只需查找sessionID就能获取会话信息,性能较好。 |
| 扩展性 | 在多服务器或者跨域环境中更易扩展。 | 在多服务器环境中需要同步session,扩展性较差。 |
| 数据大小 | JWT的大小比sessionID大,因此需要更多的带宽。 | sessionID大小稳定,对带宽需求较小。 |
| 到期时间 | 可以为每个token设置不同的过期时间。 | 所有session的过期时间通常相同。 |
| 客户端存储位置 | 可以存储在Cookie, LocalStorage, SessionStorage中 | 存储在Cookie中。 |
| 跨域问题 | 无跨域问题,且对于移动应用而言友好。 | 跨域问题复杂,需要服务器支持CORS。 |
| 状态 | 无状态,服务器不需要保存用户信息。 | 有状态,服务器需要保存用户信息。 |
| 使用场景 | 用于认证和信息交换,尤其适合单页应用(SPA)和前后端分离的项目 | 主要用于记录用户状态,适配传统的后端渲染的Web服务 |
总体上来说,JWT适用于前后端分离的API服务,它可以简化服务端的存储需求,并提供更好的跨平台兼容性和可扩展性,同时也能提供安全可靠的身份认证机制。而Session则适用于服务器渲染的Web应用,它可以提供更高的安全性和可调用性,同时也能减轻客户端的流量负担。不同的场景需要选择最适合的身份认证方案,根据实际需求进行选择。
六、总结
在本文中,我们探讨了如何在Node.js的Express框架中使用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 决定弹出何种软键盘类型,譬如numeric(纯数字键盘)。 See screenshots of all the types here. 这些值在所有平台都可用: 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 标题栏颜色渐变
大体思路: 第一步:“navigationStyle”:“custom” 第二步: template内 重点:给view添加ref“top” 第三步:添加渐变色样式 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运行原理分析
一、流程:ceph-deploy部署ceph-mon组建集群 1.ceph-deploy部署ceph-mon的工作流程及首次启动 1)通过命令创建ceph-mon,命令为:ceph-deploy create mon keyring def mon(args):if args.subcommand create:mon_create(args)elif…...
听GPT 讲K8s源代码--pkg(八)
k8s项目中 pkg/kubelet/envvars,pkg/kubelet/events,pkg/kubelet/eviction,pkg/kubelet/images,pkg/kubelet/kubeletconfig这些目录都是 kubelet 组件的不同功能模块所在的代码目录。 pkg/kubelet/envvars 目录中包含了与容器运行…...
差速驱动机器人的车轮里程计模型
一、说明 车轮测程法是指使用旋转编码器(即连接到车轮电机以测量旋转的传感器)的测程法(即估计运动和位置)。这是轮式机器人和自动驾驶汽车定位的有用技术。 在本文中,我们将通过探索差速驱动机器人的车轮里程计模型来深入研究车轮里...
Pytorch个人学习记录总结 09
目录 损失函数与反向传播 L1Loss MSELOSS CrossEntropyLoss 损失函数与反向传播 所需的Loss计算函数都在torch.nn的LossFunctions中,官方网址是: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设计师,那么需要学会的技能是非常多的,UI设计包含的知识点也比较多,那么具体做UI设计需要具备什么技能呢?来看看下面小编的详细介绍吧。 —、软件能力 一位好的ui设计师除了需要精通Photoshop.IlustratorDW.C4D等设…...
cass--单选不累加设置
打开软件,在空白处右击--选项--选择,如下: 完成后,点击确定按钮即可。...
线程结构——链表
C中的链表是一种非常常见的数据结构,它由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。 链表结构包括单向链表、双向链表和循环链表; 1.单向链表 单向链表由一系列节点组成,每个节点包含一个数据元素和…...
freeRTOS:基于(信号量+线程)的日志系统设计
1.日志的重要性 故障排查与调试:嵌入式系统通常运行在资源有限的环境中,故障排查和调试变得尤为复杂。日志系统可以记录系统在运行过程中的各种操作、状态和事件信息,方便开发人员追踪和定位问题所在。通过分析日志,可以快速找到故…...
数据可视化(1)
使用python带的matplotlib库进行简单的绘图。使用之前先进行安装,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人类偏好数据收集奖励模型迭代式微调(RLHF)拒绝采样(Rejection Sampling)PPO多轮一致性的系统消息&…...
BTY-DNS AMA回顾:致力于创建Web3领域中的去中心化身份(DID)
传统域名系统 (DNS) 是一个分层的分散信息存储,用于将用户在网络浏览器中输入可读名称(例如www.baidu.com)解析为IP地址,来访问互联网上的计算机。传统域名系统存在一些例如过于集中化管理、效率并不高等局限性问题。而去中心化域…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
