用egg.js来写一个api管理系统(一)
Egg.js是一个基于Node.js的企业级开发框架,非常适合构建API服务。
安装egg.js
首先,您需要安装Node.js和npm(Node Package Manager)。然后,您可以通过运行以下命令来安装Egg.js:
npm i egg --save
然后,您可以使用以下命令创建一个新的Egg.js项目:
npx egg-init <project-name>
接下来,您可以通过修改config/config.default.js文件来配置您的应用程序。
最后,您可以在您的Egg.js项目中编写控制器和路由,以实现您的API管理系统。
给系统加一个token验证
您可以使用JWT(JSON Web Token)来为您的API管理系统添加令牌验证。
首先,您可以在您的Egg.js项目中安装jsonwebtoken库:
npm install jsonwebtoken --save
然后,您可以在您的控制器中编写代码来生成和验证JWT令牌:
const jwt = require('jsonwebtoken');// 生成JWT令牌
const token = jwt.sign({ data: 'foobar' }, 'secret', { expiresIn: '1h' });// 验证JWT令牌
jwt.verify(token, 'secret', (err, decoded) => {if (err) {console.error(err);} else {console.log(decoded);}
});
您可以在请求头中包含JWT令牌,并在您的路由中检查令牌是否有效。如果令牌无效,则可以向用户返回401错误代码。
此外,您还可以使用Egg.js中间件来自动验证令牌,以简化代码:
// 创建令牌验证中间件
const jwtMiddleware = (req, res, next) => {const token = req.headers.authorization;if (!token) {return res.status(401).send({ error: '令牌丢失' });}try {const decoded = jwt.verify(token, 'secret');req.user = decoded;next();} catch (err) {return res.status(401).send({ error: '令牌无效' });}
};// 应用令牌验证中间件
app.use(jwtMiddleware);
请注意,以上代码仅作为示例,请不要在生产环境中使用硬编码的密钥。请使用随机生成的密钥或通过其他方式(如环境变量)安全存储密钥。
除此之外,您可以使用其他方法,如比对令牌中的用户ID与数据库中的用户记录,来进一步验证令牌的有效性。
您还可以使用Egg.js的插件机制,来简化令牌验证的流程。例如,您可以安装egg-jwt插件,它提供了一个简单的方法来处理JWT令牌验证。
最后,请注意,令牌验证是安全的关键组成部分,请确保您的代码遵循最佳安全实践,以防止令牌被滥用或窃取。
使用OAuth2.0进行令牌验证
以下是一个简单的示例,展示了如何使用Egg.js和OAuth2.0进行令牌验证:
npm install egg-oauth2-server
在config.default.js文件中,配置OAuth2.0服务器:
exports.oauth2server = {grantType: ['password', 'refresh_token'],
};
创建一个中间件,用于检查请求中是否包含令牌,并验证令牌的有效性:
// app/middleware/oauth.js
const OAuth = require('egg-oauth2-server');module.exports = (options, app) => {const oauth = new OAuth(options, app);return async function oauthMiddleware(ctx, next) {try {await oauth.authenticate();await next();} catch (err) {ctx.status = 401;ctx.body = {error: err.message,};}};
};
在所有需要认证的路由上使用该中间件:
// app/router.js
module.exports = app => {const { router, controller } = app;const oauthMiddleware = app.middleware.oauth();router.get('/api/user', oauthMiddleware, controller.user.info);
};
这是一个简单的实现,您可以根据您的需求进行调整。如果您想了解更多关于OAuth2.0的信息,请参阅OAuth2.0规范。
使用JWT进行令牌验证
使用JWT进行令牌验证的具体代码也可能因您所使用的实现而异。然而,以下是一个简单的示例,展示了如何使用Egg.js和JWT进行令牌验证:
npm install jsonwebtoken
创建一个秘密,用于加密和解密令牌:
// app/config/config.default.js
exports.jwt = {secret: 'your_secret_key',
};
创建一个中间件,用于检查请求中是否包含令牌,并验证令牌的有效性:
// app/middleware/authentication.js
const jwt = require('jsonwebtoken');module.exports = (options, app) => {return async function authenticationMiddleware(ctx, next) {const token = ctx.header.authorization;if (!token) {ctx.status = 401;ctx.body = {error: 'No token provided in request headers',};return;}try {const decoded = jwt.verify(token, app.config.jwt.secret);ctx.state.user = decoded;await next();} catch (err) {ctx.status = 401;ctx.body = {error: 'Invalid token',};}};
};
在所有需要认证的路由上使用该中间件:
// app/router.js
module.exports = app => {const { router, controller } = app;const authenticationMiddleware = app.middleware.authentication();router.get('/api/user', authenticationMiddleware, controller.user.info);
};
给每个用户一个唯一的API密钥
// app/middleware/authenticate.js
module.exports = () => {return async function authenticate(ctx, next) {const apiKey = ctx.header.apikey;// 在数据库中查找用户const user = await ctx.model.User.findOne({ apiKey });if (!user) {ctx.status = 401;ctx.body = { message: 'Unauthorized' };return;}// 将用户信息存储在上下文中,以便在其他地方使用ctx.state.user = user;await next();};
};// app/router.js
module.exports = app => {const { router, middleware } = app;const authenticate = middleware.authenticate();router.get('/api/v1/resources', authenticate, ctx => {// 访问 API 资源});
};
这个代码示例使用一个中间件函数来验证请求中的API密钥。如果密钥是有效的,则该中间件函数将用户信息存储在上下文中,并将控制传递给下一个中间件函数或路由处理程序。如果密钥是无效的,则中间件函数将返回401 Unauthorized响应。
限制用户的访问次数
您可以通过记录并限制每个用户的API请求数来限制用户的访问次数。
可以在存储用户数据的数据库中添加一个字段,用于记录每个用户在特定时间段内对API的访问次数。每当用户对API进行请求时,您可以将其请求数加1。如果用户的请求数超过了限制,则拒绝其请求并向其返回适当的错误消息。
代码实现的示例如下:
// app/middleware/api_key_auth.js
const jwt = require('jsonwebtoken');
const { secret } = require('config').security;module.exports = (options, app) => {return async function apiKeyAuth(ctx, next) {// 获取请求头中的 API Keyconst apiKey = ctx.headers['x-api-key'];// 验证 API Key 是否存在if (!apiKey) {ctx.status = 401;ctx.body = { error: 'Unauthorized' };return;}// 验证 API Key 是否正确try {const decoded = jwt.verify(apiKey, secret);const user = await app.models.User.findOne({ apiKey: decoded.apiKey });// 验证 API Key 对应的用户是否存在if (!user) {ctx.status = 401;ctx.body = { error: 'Unauthorized' };return;}// 验证用户访问次数是否超限if (user.requestCount >= user.requestLimit) {ctx.status = 429;ctx.body = { error: 'Too Many Requests' };return;}// 将用户的信息挂载到 ctx 上,方便在后续的处理中使用ctx.user = user;// 将用户的访问次数加 1await app.models.User.updateOne({ apiKey: decoded.apiKey }, { $inc: { requestCount: 1 } });// 继续执行后续的请求处理await next();} catch (err) {ctx.status = 401;ctx.body = { error: 'Unauthorized' };}};
};// config/config.default.js
module.exports = {security: {secret: 'your secret'}
};// app/router.js
module.exports = app => {const { router, controller } = app;router.get('/', controller.home.index);router.get('/secret', app.middleware.apiKeyAuth(), controller.home.secret);
};
请注意,在这个示例中,用户数据是写死在代码中的,在生产环境中,您应该将用户数据存储在数据库中以便更好地管理。
相关文章:
用egg.js来写一个api管理系统(一)
Egg.js是一个基于Node.js的企业级开发框架,非常适合构建API服务。 安装egg.js 首先,您需要安装Node.js和npm(Node Package Manager)。然后,您可以通过运行以下命令来安装Egg.js: npm i egg --save然后&a…...

企业数字化转型和升级:架构设计方法与实践
目录 企业架构整体结构 企业架构的驱动力 企业架构的基本概念 企业架构的发展 企业架构框架理论 主流企业架构框架之对比 企业架构整体结构 图例:企业架构整体结构 企业架构整体结构从战略层、规划层、落地层这三层来分别对应企业架构中 业务、架构和实施的各种重要…...

【LeetCode】环形链表 II [M](链表)
142. 环形链表 II - 力扣(LeetCode) 一、题目 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链…...
Unity之如何实现一个VR任务(剧情)系统
一.前言 最近再做一个VR项目,里面有大量的剧情和VR操作任务。 比如: 1.张三说了什么话,干了什么事,然后,李四又说了什么,做了什么动画,完了之后,场景中某个物体高亮,让我们触摸或者射线点击(pc的话鼠标点击)和其发生交互。 2.我们使用VR手柄或者鼠标与场景中的一个…...

k8s核心概念与kubectl命令行工具的使用
k8s官方文档Kubernetes 文档 | Kubernetes作用:kubernetes用于容器化应用程序的部署,扩展和管理。目标:是让部署容器化应用简单高效。Kubernetes集群架构与组件 Master组件 kube-apiserverkubernetes API,集群的统一入口ÿ…...

【零基础入门前端系列】—无序列表、有序列表、定义列表(四)
一、HTML无序列表 无序列表是一个项目的列表,此列项目使用粗体圆点(典型的小黑圆圈)进行标记。 无序列表使用 <ul> 标签 <ul> <li>Coffee</li> <li>Milk</li> </ul>嵌套结构: <…...

为什么重写equals还要重写hashcode方法
目录equals方法hashCode方法为什么要一起重写?总结面试如何回答重写 equals 时为什么一定要重写 hashCode?要想了解这个问题的根本原因,我们还得先从这两个方法开始说起。 以下是关于hashcode的一些规定: 两个对象相等࿰…...

电子技术——电流镜负载的差分放大器
电子技术——电流镜负载的差分放大器 目前我们学习的差分放大器都是使用的是差分输出的方式,即在两个漏极之间获取电压。差分输出主要有以下优势: 降低了共模信号的增益,提高了共模抑制比。降低了输入偏移电压。提升了差分输入的增益。 由于…...
go面试题
1.json包在使用的时候,结构体里的变量不加tag能不能正常转成json里的字段? 如果变量首字母小写,则为private。无论如何不能转,因为取不到反射信息。如果变量首字母大写,则为public。 不加tag,可以正常转为j…...

攻防世界-Confusion1
题目 访问题目场景 某天,Bob说:PHP是最好的语言,但是Alice不赞同。所以Alice编写了这个网站证明。在她还没有写完的时候,我发现其存在问题。(请不要使用扫描器) 然后结合图片我们知道,这个网址是python写的࿰…...

机器学习实战--梯度下降法进行波士顿房价预测
前言: Hello大家好,我是Dream。 今天来学习一下如何使用机器学习梯度下降法进行波士顿房价预测,这是简单的一个demo,主要展示的是一些小小的思路~ 本文目录:一、波士顿房价预测1.全部的数据可视化2.地理数据可视化3.房…...

黑马】后台管理-项目优化和上线
一。项目优化优化1,加载进度条显示安装一个运行依赖,nprogress然后导包,调用对象展示和隐藏在main中基于拦截器实现展示进度条和隐藏进度条的效果如果触发请求拦截器,证明发起请求,希望展示进度条,如果触发…...
Web 框架 Flask 快速入门(三)数据库-MySQL
课程地址:Python Web 框架 Flask 快速入门 文章目录数据库1、数据库的安装与配置2、数据库的简单使用——增删改1. 定义数据模型2. 增删改3、 关系引用——表的关联4、查询——通过SQLAlchemy扩展5、其他1. 数据模型的实现(疑惑)6、Bug记录1.…...

牛客网Python篇数据分析习题(六)
1.某公司计划举办一场运动会,现有运动会项目数据集items.csv。 包含以下字段: item_id:项目编号; item_name:项目名称; location:比赛场地。 有员工报名情况数据集signup.csv。包含以下字段: employee_id&a…...

Ansible的安装及部署
目录 一、Ansible对于企业运维的重大意义 二、Ansible的安装 三、构建Ansible清单 1.直接书写受管主机名或ip,每行一个 2.设定受管主机的组[组名称] 四、Ansible配置文件参数详解 1、配置文件的分类与优先级 2.配置新用户的Ansible配置 3.生成免密认证 本章…...

链表题目总结 -- 递归
目录一. 递归反转整个链表1. 思路简述2. 代码3. 总结二. 反转链表前 N 个节点1. 思路简述2. 代码3. 总结三、反转链表的一部分1. 思路简述2. 代码3.总结四、从节点M开始反转后面的链表1. 思路简述2. 代码3.总结一. 递归反转整个链表 题目链接:https://leetcode.cn/…...

重写-linux内存管理-伙伴分配器(一)
文章目录一、伙伴系统的结构二、初始化三、分配内存3.1 prepare_alloc_pages3.2 get_page_from_freelist3.2.1 zone_watermark_fast3.2.2 zone_watermark_ok3.2.3 rmqueue3.2.3.1 rmqueue_pcplist3.2.3.2 __rmqueue3.2.3.2.1 __rmqueue_smallest3.2.3.2.2 __rmqueue_fallback3.…...

为什么要用springboot进行开发呢?
文章目录前言1、那么Springboot是怎么实现自动配置的1.1 启动类1.2 SpringBootApplication1.3 Configuration1.4 ComponentScan1.5 EnableAutoConfiguration1.6 两个重要注解1.7 AutoConfigurationPackage注解1.8 Import(AutoConfigurationImportSelector.class)注解1.9自动配置…...
设备树信息解析相关函数
一。可以通过三种不同的方式解析设备树节点: 1.根据设备树节点的名字解析设备树节点 struct device_node *of_find_node_by_name(struct device_node *from, const char *name); 参数: from:当前节点父节点首地址 name:设备树节点名字 …...
LeetCode-1124. 表现良好的最长时间段【哈希表,前缀和,单调栈】
LeetCode-1124. 表现良好的最长时间段【哈希表,前缀和,单调栈】题目描述:解题思路一:查字典。cur是当前的前缀和(劳累与不劳累天数之差),向前遍历。有两种情况。情况一,若cur大于0则是[0,i]的劳累与不劳累天…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...

9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...

算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...

Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...