Node.js 中如何进行 JWT(JSON Web Tokens)身份验证和授权

目录

JWT 使用场景

JWT 基本概念

常用方法

1. 生成 JWT

2. 验证 JWT

3. 中间件

实践案例

项目实战

封装jwt文件

后端登录接口生成token 设置为响应头

全局路由中间件验证token

前端拦截处理token

提示、技巧和注意事项


JWT 是一种用于安全传输信息的开放标准,它通常用于身份验证和授权。在 Node.js 中,你可以使用库如jsonwebtoken来创建和验证 JWT。JWT 允许你在服务器和客户端之间安全地传递信息,而无需存储会话状态。这使得 JWT 非常适合构建分布式系统,如单页应用(SPA)、移动应用和微服务。

JWT 使用场景

在什么情况下使用 JWT 是有意义的?以下是一些常见的使用场景:

  1. 用户身份验证: JWT 可用于验证用户的身份。当用户登录时,服务器可以为其生成一个 JWT,客户端可以在后续请求中发送这个 JWT 来证明其身份。
  2. 单点登录(SSO): JWT 可以用于实现单点登录,让用户一次登录即可访问多个相关应用,而无需重复登录。
  3. API 授权: 在 API 调用中,JWT 可以包含授权信息,以便在服务器端验证用户是否有权限执行特定操作。
  4. 密码重置: JWT 可用于安全地生成包含重置密码令牌的链接,以允许用户重置其密码。
  5. 移动应用认证: 移动应用可以使用 JWT 来与后端服务器进行身份验证,确保只有经过授权的用户可以访问后端资源。

JWT 基本概念

在 Node.js 中使用 JWT,你需要了解以下基本概念:

  1. JWT 结构: JWT 由三部分组成,分别是头部(Header)、载荷(Payload)和签名(Signature)。头部包含算法和令牌类型,载荷包含要传递的信息,签名用于验证令牌的真实性。
  2. 密钥: 生成和验证 JWT 时,你需要一个密钥。密钥可以是对称密钥(使用相同的密钥进行签名和验证)或非对称密钥(使用不同的密钥进行签名和验证)。
  3. 签名验证: 接收 JWT 的服务器使用密钥验证签名以确保 JWT 未被篡改。如果签名验证成功,服务器可以信任 JWT 中的信息。

常用方法

以下是在 Node.js 中进行 JWT 身份验证和授权的常用方法:

1. 生成 JWT

使用jsonwebtoken库可以生成 JWT。首先,你需要安装该库:

npm install jsonwebtoken

然后,你可以使用以下代码生成 JWT:

const jwt = require('jsonwebtoken');const payload = { userId: 123, role: 'admin' };
const secretKey = 'your-secret-key';const token = jwt.sign(payload, secretKey, { expiresIn: '1h' });

2. 验证 JWT

服务器收到 JWT 后,需要验证其真实性。使用以下代码验证 JWT:

const jwt = require('jsonwebtoken');const token = 'your-jwt-token';
const secretKey = 'your-secret-key';try {const decoded = jwt.verify(token, secretKey);console.log(decoded);
} catch (error) {console.error('JWT verification failed');
}

3. 中间件

在 Express.js 中,你可以创建 JWT 验证中间件来保护特定路由。以下是一个示例:

const jwt = require('jsonwebtoken');
const secretKey = 'your-secret-key';function authenticateToken(req, res, next) {const token = req.header('Authorization');if (!token) return res.status(401).send('Access denied');try {const decoded = jwt.verify(token, secretKey);req.user = decoded;next();} catch (error) {res.status(403).send('Invalid token');}
}

实践案例

让我们通过一个实际案例来演示如何在 Node.js 中进行 JWT 身份验证和授权。我们将创建一个简单的 Express.js 应用,并使用 JWT 来保护一个受限的路由。

const express = require('express');
const jwt = require('jsonwebtoken');
const secretKey = 'your-secret-key';const app = express();
app.use(express.json());// 登录路由,生成JWT
app.post('/login', (req, res) => {const { username, password } = req.body;// 在实际应用中,这里会验证用户名和密码if (username === 'user' && password === 'password') {const payload = { username };const token = jwt.sign(payload, secretKey, { expiresIn: '1h' });res.json({ token });} else {res.status(401).json({ error: 'Authentication failed' });}
});// 受保护的路由,需要JWT验证
app.get('/protected', authenticateToken, (req, res) => {res.json({ message: 'This is a protected route', user: req.user });
});function authenticateToken(req, res, next) {const token = req.header('Authorization');if (!token) return res.status(401).send('Access denied');try {const decoded = jwt.verify(token, secretKey);req.user = decoded;next();} catch (error) {res.status(403).send('Invalid token');}
}app.listen(3000, () => {console.log('Server is running on port 3000');
});

在上面的示例中,我们创建了一个登录路由,生成 JWT 并将其返回给客户端。然后,我们创建了一个受保护的路由,使用authenticateToken中间件来验证 JWT。如果 JWT 验证成功,用户将能够访问受保护的路由。

项目实战

封装jwt文件

const jsonwebtoken = require("jsonwebtoken");
const secrcet = "贾公子";
const JWT = {// 生成tokengenerate(value, exprires) {// 加密内容 密钥 过期时间return jsonwebtoken.sign(value, secrcet, { expiresIn: exprires });},// token 解密verify(token) {try {return jsonwebtoken.verify(token, secrcet);} catch (error) {return false;}},
};module.exports = JWT;

后端登录接口生成token 设置为响应头

   login: async (req, res) => {console.log(req.body);// req.bodyvar result = await UserService.login(req.body)if (result.length == 0) {res.send({code: '-1',error: '用户名密码不匹配'})} else {// 生成token const token = JWT.generate({_id: result[0]._id,username: result[0].username}, '1d')res.header('Authoization', token)res.send({ActionType: 'ok',data: {username: result[0].username,gender: result[0].gender ? result[0].gender : 0, //性别 0 1 2introduction: result[0].introduction,//简介avatar: result[0].avatar,role: result[0].role,//管理员1 编辑2}})}},

全局路由中间件验证token

  // 如果token有效,next()
  // 如果token过期了,返回401

每次访问刷新token 延续token

app.use((req, res, next) => {// 如果token有效,next()// 如果token过期了,返回401if (req.url == '/adminapi/user/login') {next()return}const token = req.headers['authoization'].split(' ')[1]if (token) {let payload = JWT.verify(token)console.log(payload);if (payload) {const newToken = JWT.generate({_id: payload._id,username: payload.username}, '1d')res.header('Authoization', newToken)next()} else {res.status(401).send({ errCode: '-1', errorInfo: 'token过期' })}}

前端拦截处理token

import axios from 'axios'; // 引入axios
axios.interceptors.request.use(Config => {const token = localStorage.getItem('token')Config.headers.Authoization = `Beare ${token}`return Config
})
axios.interceptors.response.use(function (response) {// console.log(response.headers);const { authoization } = response.headersauthoization && localStorage.setItem('token', authoization)return response
}, function (error) {const { status } = error.responseif (status == 401) {localStorage.removeItem('token')window.location.href = '#/login'return Promise.reject(error)}
})


 

提示、技巧和注意事项

  • 安全存储密钥: 密钥是 JWT 的关键部分,应安全存储。不要硬编码密钥,最好从环境变量或配置文件中读取。
  • 定期刷新令牌: 为 JWT 设置适当的到期时间,以降低安全风险。客户端应定期获取新的 JWT 令牌。
  • 不要在 JWT 中存储敏感信息: 避免在 JWT 中存储敏感信息,因为 JWT 可以被解码。如果需要存储敏感信息,应使用加密而不是签名。
     

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初识Django

前言: 各位观众老爷们好,最近几个月都没怎么更新,主要是最近的事情太多了,我也在继续学习Django框架,之前还参加了一些比赛,现在我会开始持续更新Django的学习,这个过程会比较久,我会把我学习的…

微积分-反函数6.5(指数增长和衰减)

在许多自然现象中,数量的增长或衰减与其大小成正比。例如,如果 y f ( t ) y f(t) yf(t) 表示在时间 t t t 时某种动物或细菌种群的个体数量,那么似乎可以合理地假设增长速率 f ’ ( t ) f’(t) f’(t) 与种群 f ( t ) f(t) f(t) 成正比…

Redis的基本使用

简介 传统的数据库是 关系数据库,但是Redis是键值对数据库传统的数据库是基于 磁盘存储的,但是Redis是基于 内存存储的 基于内存,读写性能更高内存是不大的,只能存储热点信息 安装 绿色软件,安装即可使用 安装服务 手…

【MySQL】子查询、合并查询、表的连接

目录 一、子查询 1、单行子查询 显示SMITH同一部门的员工信息 2、多行子查询 in关键字 查询和10号部门的工作岗位相同的雇员的名字、岗位、工资、部门号,但是筛选出的雇员的部门不能有10号部门 all关键字 查询工资比30号部门中所有雇员工资高的雇员的姓名、…

LLM端侧部署系列 | PowerInfer-2助力AI手机端侧部署47B大模型 (论文解读)

引言 简介 PowerInfer-2 概述 神经元感知的运行时推理 多态神经元引擎 内存中的神经元缓存 灵活的神经元加载 Neuron-Cluster-Level Pipeline 生成执行计划 执行 总结 0. 引言 一雨池塘水面平,淡磨明镜照檐楹。东风忽起垂杨舞,更作荷心万点声…

十、敌人锁定

方法:通过寻找最近的敌人,使玩家的面朝向始终朝向敌人,进行攻击 1、代码 在这个方法中使用的是局部变量,作为临时声明和引用 public void SetActorAttackRotation() {Enemys GameObject.FindGameObjectsWithTag("Enemy&qu…

工程机械车辆挖掘机自卸卡车轮式装载机检测数据集VOC+YOLO格式2644张3类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2644 标注数量(xml文件个数):2644 标注数量(txt文件个数):2644 标注…

Vue+NestJS项目实操(图书管理后台)

一、项目搭建 前端基于vben进行二次开发 在Github下载vben框架,搜索vben即可 下载地址:https://github.com/vbenjs/vue-vben-admin 下载完成后,进行安装依赖,使用命令: // 下载依赖 pnpm install// 运行项目 pnpm …

每日一练:地下城游戏

174. 地下城游戏 - 力扣(LeetCode) 题目要求: 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔…

基于facefusion的换脸

FaceFusion是一个引人注目的开源项目,它专注于利用深度学习技术实现视频或图片中的面部替换。作为下一代换脸器和增强器,FaceFusion在人脸识别和合成技术方面取得了革命性的突破,为用户提供了前所未有的视觉体验。 安装 安装基础软件 安装…

数据链路层(以太网简介)

一.以太网数据帧结构: 目的地址,源地址,类型这三个被称为帧头,数据则被称为载荷,CRC则被称为帧尾(校验和) 二.数据帧结构分析 1.目的地址和源地址 i.地址解释 这两个地址指的是mac地址&#x…

国庆游玩计划安排

地点:上海前滩四方城 地点:船长酒吧 地点:上海🏛️外滩华尔道夫

httpsok-v1.17.0-SSL通配符证书自动续签

🔥httpsok-v1.17.0-SSL通配符证书自动续签 介绍 httpsok 是一个便捷的 HTTPS 证书自动续签工具,基于全新的设计理念,专为 Nginx 、OpenResty 服务器设计。已服务众多中小企业,稳定、安全、可靠。 一行命令,一分钟轻…

HTML基础用法介绍一

VS code 如何快速生成HTML骨架注释是什么?为什么要写注释?注释的标签是什么?标题标签段落标签换行标签与水平线标签 (都是单标签)文本格式化标签图片标签超链接标签音频标签视频标签 🚘正片开始 VS code 如何快速生成…

深度学习每周学习总结J1(ResNet-50算法实战与解析 - 鸟类识别)

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 | 接辅导、项目定制 目录 0. 总结1. 设置GPU2. 导入数据及处理部分3. 划分数据集4. 模型构建部分5. 设置超参数:定义损失函数,学习率&a…

STM32+PWM+DMA驱动WS2812 —— 2024年9月24日

一、项目简介 采用STM32f103C8t6单片机,使用HAL库编写。项目中针对初学者驱动WS2812时会遇到的一些问题,给出了解决方案。 二、ws2812驱动原理 WS2812采用单线归零码的通讯方式,即利用高低电平的持续时间来确定0和1。这种通信方式优点是只需…

Vue 学习

vue 核心语法 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Vue 核心语法测试</title> </head><body&…

外包功能测试干了4年,技术退步太明显了。。。。。​

先说一下自己的情况&#xff0c;本科生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了差不多4年的功能测试&#xff0c;今年中秋&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测…

信号用wire类型还是reg类型定义

wire类型就是一根线&#xff0c;线有两端&#xff0c;一端发生改变&#xff0c;经过线传递的信号当然也会发生改变&#xff0c;reg类型则不同&#xff0c;可以把reg类型理解为存储数据的寄存器&#xff0c;当满足一定条件时&#xff0c;数值才被激活发生改变。 那么&#xff0…

【AI论文精读1】针对知识密集型NLP任务的检索增强生成(RAG原始论文)

目录 一、简介一句话简介作者、引用数、时间论文地址开源代码地址 二、摘要三、引言四、整体架构&#xff08;用一个例子来阐明&#xff09;场景例子&#xff1a;核心点&#xff1a; 五、方法 &#xff08;架构各部分详解&#xff09;5.1 模型1. RAG-Sequence Model2. RAG-Toke…