MongoDB——Mongoose

本文介绍了Mongoose,它是用于通过Node操作MongoDB的模块,有创建模式结构、验证文档对象等优点,还提供了Schema、Model等对象。接着说明了其使用步骤,包括环境搭建和增删改查操作。最后探讨了MongoDB的事务问题,以及前端直接对接数据库的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Mongoose简介
 Mongoose是一个让我们可以通过Node来操作MongoDB的模块,是一个对象文档模型(ODM),它对Node原生的MongoDB模块进行了进一步的优化封装,并提供了更多的功能。大多数情况下,Mongoose被用来把结构化的模式应用到一个MongoDB集合,并提供验证和类型转换等。简单的说它是前端开发用来操作MongoDB的一个工具,类似于后台开发使用Mybatis等操作Mysql。
 Mongoose的优点:
  1️⃣可以为文档创建一个模式结构(Schema),用来约束MongoDB中的文档对象
  2️⃣可以对模型中的文档对象进行验证
  3️⃣数据可以通过类型转换转换为对象模型
  4️⃣可以使用中间件来与应用的业务逻辑挂钩
 Mongoose为我们提供了几个对象:
  ①Schema(模式对象):约束数据库中的文档对象的结构
  ②Model:作为集合中所有文档对象的表示,相当于MongoDB数据库中的collection
  ③Document:表示集合中的具体文档,相当于集合中的一个具体文档
 其他语言与MongoDB的对接请参考:菜鸟教程

二、Mongoose的使用
 使用Mongoose时,必须先先有schema,再通过schema创建model,最后通过model创建document。
 1、环境搭建
  ①在工程中引入Mongoose依赖

npm i mongoose --save

  ②在项目中引入mongoose

var mongoose = require("mongoose");

  ③使用mongoose连接MongoDB数据库:mongoose_test是数据库名,不需要事先创建,若端口号是默认的27017,则可以不写

mongoose.connect("mongodb://127.0.0.1/mongoose_test" , { useMongoClient: true});

  ④监听数据库的连接状态

mongoose.connection.once("open",function(){
	console.log("数据库连接成功~~~");
});

mongoose.connection.once("close",function(){
	console.log("数据库连接已经断开~~~");
});

  ⑤断开连接:一般不需要调用

//断开数据库连接
mongoose.disconnect();

 2、使用操作mongoose进行MongoDB的增删改查等操作
  ①使用mongoose.Schema创建schema对象

//将mongoose.Schema赋值给一个新变量,也可以直接只用mongoose.Schema
var Schema = mongoose.Schema;

//创建Schema对象:schema对象是对由其创建的Model(可看做是collection)中的所有文档对象的约束
var stuSchema = new Schema({
	name:String,
	age:Number,
	gender:{
		type:String,
		default:"female"
	},
	address:String
});

  ②通过Schema来创建Model:Model代表的是数据库中的集合,通过Model才能对数据库进行操作,这些操作的详情请参考官方文档

//mongoose会自动将集合名变成复数
var StuModel = mongoose.model("student" , stuSchema);

//向数据库中插入一个文档
StuModel.create({
	name:"白骨精",
	age:16,
	address:"白骨洞"
},function (err) {
	if(!err){
		console.log("插入成功~~~");
	}
});

StuModel.find({name:"唐僧"},function (err , docs) {
	if(!err){
		console.log(docs);
	}
});

StuModel.find({},{name:1 , _id:0},function (err , docs) {
	if(!err){
		console.log(docs);
	}
});

StuModel.find({},"name age -_id", {skip:3 , limit:1} , function (err , docs) {
	if(!err){
		console.log(docs);
	}
});

StuModel.findOne({} , function (err , doc) {
	if(!err){
		console.log(doc);
	}
});

StuModel.findById("59c4c3cf4e5483191467d392" , function (err , doc) {
	if(!err){
		//通过find()查询的结果,返回的对象,就是Document,文档对象
		//Document对象是Model的实例
		console.log(doc instanceof StuModel);
	}
});

StuModel.updateOne({name:"唐僧"},{$set:{age:20}},function (err) {
	if(!err){
		console.log("修改成功");
	}
});

StuModel.remove({name:"白骨精"},function (err) {
	if(!err){
		console.log("删除成功~~");
	}
});

StuModel.count({},function (err , count) {
	if(!err){
		console.log(count);
	}
});

三、事务问题
 MongoDB作为数据库必然存在事务问题,那么事务有没有可能通过前端解决呢?答案是不可能。原因很简单,前端其实就是用户的个人电脑,各个用户之间的电脑可能是相互不通信的,那么就不可能仅通过前端解决事务的问题。举例来说:用户A从MongoDB中查询出_id是123456的文档对象,想修改该对象的一个属性值,此时用户B也查询出_id为123456的该对象,但在A完成修改之前B将其删除了,那么A的操作必然是失败的,其他诸类操作也会面临这个问题。既然前端不可能完成事务控制,那能不能将事务控制交给MongoDB呢?比如说一旦有用户查询_id为123456的对象,就将该对象加锁,直到该用户操作完该对象,其他用户才允许查询和修改该对象,理论上这是可以的。其实这和MySQL等是一个逻辑,这其中也必然需要通过事务隔离级别等对数据的读写性能进行取舍。
 那么一个可怕的问题来了:对于web应用来说(app可能会导致安装过于庞大,手机会扛不住),前端直接对接数据库,相当于将所有的运算都放在了用户自己的电脑上,以现在电脑的配置是不成问题的,更何况此时每个用户的电脑只需要处理用户自己的数据,计算的压力其实是很小的,当然这对浏览器的要求要更高;还有一点这样一来企业的成本也会大大降低(需要的服务器数量大大减少了,只需要两台服务器:一台前端服务器,一台数据库服务器,数据库服务器可酌情增加,有高并发时再还一些中间件的加持),这不是比后台分布式更有优势吗?后台分布式部署的目的不就是为了转移计算机的计算压力吗?还有什么方式能比将计算压力转移给用户自己更加符合分布式的需求呢?而后台分布式再怎么分开部署一台服务器也需要处理成千上万个用户的数据,这么一想后台岂不是没有了存在的必要?

<think>我们正在处理关于MongoDBMongoose搜索注入漏洞CVE-2025-23061的查询。根据提供的引用,我们需要整合信息,提供详细的漏洞分析、影响和修复方案。关键引用信息:-引用[1]:CVE-2025-23061影响Mongoose8.9.5、7.8.4和6.13.6之前的版本,原因是$where运算符的不当使用,导致可能执行任意JavaScript代码,造成代码注入攻击,从而未授权访问或操纵数据库。该漏洞是CVE-2024-53900修复不完整导致的。-引用[2]:CVE-2024-53900是之前的一个类似漏洞,同样涉及$where运算符的不当使用。-引用[4]:指出CVE-2024-53900的补丁增加了检查,禁止直接传递$where操作符,但攻击者可以通过将$where嵌入$or操作符中绕过补丁,导致CVE-2025-23061。因此,我们可以这样组织回答:1.漏洞描述:介绍CVE-2025-23061的基本情况,包括漏洞原因、影响版本等。2.漏洞影响:说明漏洞可能造成的后果。3.修复方案:提供升级到安全版本的建议,并说明如何避免类似问题。4.补充建议:给出安全使用Mongoose的最佳实践。同时,根据系统指令,我们需要在回答中自然地添加引用标识,并在末尾生成相关问题。注意:我们引用的内容来自用户提供的引用[1]、[2]、[4],所以引用标识使用[^1]、[^2]、[^4]。回答结构:-使用中文-行内数学表达式用$...$,独立公式用$$...$$(但本问题可能不需要数学公式)-生成相关问题具体回答:</think>### MongoDB Mongoose 搜索注入漏洞 CVE-2025-23061 分析及修复方案 #### **1. 漏洞描述** - **根本原因**:MongooseMongoDB 查询中未充分限制 `$where` 操作符的使用,导致攻击者可构造恶意查询执行任意 JavaScript 代码[^1][^4]。该漏洞源于对 **CVE-2024-53900** 的修复不完整——补丁仅禁止直接传递 `$where`,但未检测嵌套在 `$or` 等操作符中的 `$where` 子句[^4]。 - **影响版本**: - Mongoose `< 8.9.5` - Mongoose `< 7.8.4` - Mongoose `< 6.13.6`[^1] #### **2. 攻击原理** 攻击者通过注入类似以下结构的恶意查询: ```javascript { $or: [ { normal_field: "value" }, { $where: "malicious_javascript_code" } // 嵌套绕过检测 ] } ``` 当服务端使用 `Model.find()` 等易受攻击函数处理此查询时,`$where` 中的 JavaScript 代码将在数据库进程内执行,导致: - **未授权数据访问/篡改**:读取或修改数据库内容[^1]。 - **远程代码执行 (RCE)**:结合 Node.js 环境特性,可能升级为服务器 RCE(参考类似漏洞 CVE-2019-10758)[^3][^4]。 #### **3. 影响分析** | 影响维度 | 具体后果 | |----------------|--------------------------------------------------------------------------| | **机密性** | 攻击者可窃取数据库敏感信息(如用户凭证、隐私数据) | | **完整性** | 篡改或删除数据(如订单记录、配置信息) | | **可用性** | 通过高负载 JavaScript 操作拖垮数据库性能 | | **横向威胁** | 若数据库服务权限较高,可能进一步渗透服务器(如触发堆溢出漏洞 CVE-2024-XXXX)[^5] | #### **4. 修复方案** **立即升级**至安全版本: ```bash npm install mongoose@8.9.5+ # 或 7.8.4+/6.13.6+ ``` **代码层加固**: - **禁用 `$where`**:全局禁止使用 `$where` 操作符 ```javascript mongoose.set('sanitizeFilter', true); // 启用严格模式过滤危险操作符 ``` - **输入验证**:对所有查询参数进行类型/结构检查 ```javascript function safeQueryFilter(input) { if (typeof input !== 'object') throw new Error("Invalid query"); // 递归检测并删除 $where 子句 const removeWhere = (obj) => { Object.keys(obj).forEach(key => { if (key === '$where') delete obj[key]; else if (typeof obj[key] === 'object') removeWhere(obj[key]); }); }; removeWhere(input); return input; } // 使用示例 Model.find(safeQueryFilter(userInput)); ``` #### **5. 漏洞关联** - **CVE-2024-53900**:本漏洞的前序漏洞,修复后因检测逻辑不完善被绕过[^2][^4]。 - **防御深度建议**:结合 MongoDB 的 `--noscripting` 启动参数禁用 JavaScript 引擎(需评估业务依赖)[^3]。 ### 总结 CVE-2025-23061 是高风险注入漏洞,需立即升级 Mongoose 并加固查询处理逻辑。根本解决方案是**避免在查询中动态拼接用户输入**,并严格限制 MongoDB 的 JavaScript 执行能力[^1][^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值