使用AdonisJS和Mongoose连接MongoDB时认证失败求助
AdonisJS + Mongoose 连接MongoDB认证失败问题解决建议
错误原因分析
错误码18 (AuthenticationFailed)明确指向MongoDB认证环节失败,常见原因包括:连接字符串未指定认证源、用户权限不足、代码连接逻辑不合理。
具体修改建议
1. 修正MongoDB连接字符串
默认情况下MongoDB的root用户创建在admin数据库下,连接时必须指定认证源,否则会在目标库(todo)中查找用户导致失败。修改连接字符串:
const MONGOURI = 'mongodb://root:1234@localhost:27017/todo?authSource=admin';
如果是MongoDB 4.0+版本,可强制使用更安全的SCRAM认证机制:
const MONGOURI = 'mongodb://root:1234@localhost:27017/todo?authSource=admin&authMechanism=SCRAM-SHA-256';
2. 重构数据库连接逻辑(避免重复连接)
原代码在控制器构造函数中初始化连接,会导致每次请求都创建新连接,既浪费资源又可能引发异常。AdonisJS推荐用服务提供者统一管理数据库连接:
创建Mongoose服务提供者(app/Providers/MongooseProvider.ts)
import type { ApplicationContract } from '@ioc:Adonis/Core/Application' import mongoose from 'mongoose' export default class MongooseProvider { constructor(protected app: ApplicationContract) {} // 应用启动时初始化连接 public async boot() { // 建议将连接字符串配置到config/database.ts,避免硬编码 const mongoUri = this.app.config.get('database.mongoUri') try { await mongoose.connect(mongoUri) console.log('✅ MongoDB连接成功') } catch (error) { console.error('❌ MongoDB连接失败:', error) process.exit(1) } } // 应用关闭时断开连接 public async shutdown() { await mongoose.disconnect() console.log('🔌 MongoDB已断开连接') } }
在start/app.ts中注册提供者
providers: [ // ...其他默认提供者 () => import('App/Providers/MongooseProvider'), ]
3. 独立定义Mongoose模型(避免重复定义)
原代码在index方法中每次请求都重新创建模型,会触发Mongoose重复定义的警告。将模型单独抽离:
创建Task模型(app/Models/Task.ts)
import mongoose, { Schema, Model } from 'mongoose' // 定义文档类型接口 interface TaskDocument extends mongoose.Document { name: string description: string } // 定义Schema const TaskSchema = new Schema<TaskDocument>({ name: { type: String, required: true }, description: String }) // 导出模型 const Task: Model<TaskDocument> = mongoose.model<TaskDocument>('Task', TaskSchema) export default Task
4. 简化控制器代码
'use strict' import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' import Task from 'App/Models/Task' export default class TasksController { public async index ({ response }: HttpContextContract) { try { // 创建任务 const task = new Task({ name: Math.random().toString(36).substring(7), description: "This is description of the task." }) await task.save() // 查询所有任务 const tasks = await Task.find() return response.json(tasks) } catch (error) { return response.status(500).json({ error: error.message }) } } }
5. 验证MongoDB用户权限(可选)
如果修改连接字符串后仍失败,确认root用户拥有todo数据库的读写权限,或创建专用用户:
# 进入MongoDB shell mongo # 认证root用户 use admin db.auth('root', '1234') # 切换到todo数据库 use todo # 创建专用用户 db.createUser({ user: 'todo_user', pwd: 'your_secure_password', roles: [{ role: 'readWrite', db: 'todo' }] })
此时连接字符串改为:
const MONGOURI = 'mongodb://todo_user:your_secure_password@localhost:27017/todo?authSource=todo';
内容的提问来源于stack exchange,提问作者Chris Dean
相关产品推荐
相关产品推荐

