Next.js集成Auth Js添加MongoClient遇Edge Runtime错误及凭证登录问题
解决方案:Edge Runtime错误修复与Credentials登录实现
一、Edge Runtime错误原因与修复
错误「Edge Runtime不支持Node.js 'crypto'模块」的核心原因是:auth.config.js会被Next.js的Edge Runtime(如Middleware、Edge Routes)加载,而MongoClient、bcrypt这类库依赖Node.js专属的crypto模块,无法在Edge环境运行。
修复方案:
- 不在
auth.config.js中引入任何依赖Node.js模块的代码(数据库操作、bcrypt等),仅保留基础的Credentials配置。 - 将需要Node.js环境的逻辑(数据库查询、密码验证)移至
auth.js中,因为auth.js导出的NextAuth handlers默认运行在Node.js环境。
二、完整Credentials登录实现步骤
1. 调整auth.config.js
仅保留Credentials的基础配置,移除数据库相关逻辑:
// auth.config.js import { NextAuthConfig } from "next-auth"; import Credentials from "next-auth/providers/credentials"; const authConfig = { providers: [ Credentials({ credentials: { email: { label: "邮箱", type: "email", placeholder: "your@email.com" }, password: { label: "密码", type: "password" }, }, // 暂留空实现,后续在auth.js中覆盖 authorize: () => null, }), ], // 可选:指定自定义登录页路径 pages: { signIn: "/login", }, }; export default authConfig;
2. 修改auth.js,实现完整登录逻辑
在auth.js中扩展Credentials的authorize函数,引入数据库操作与bcrypt密码验证:
// auth.js import NextAuth from "next-auth"; import authConfig from "./auth.config"; import { MongoDBAdapter } from "@auth/mongodb-adapter"; import clientPromise from "./lib/db"; import bcrypt from "bcrypt"; import { getUserFromDB } from "./lib/db-utils"; export const { handlers, auth, signIn, signOut } = NextAuth({ adapter: MongoDBAdapter(clientPromise), session: { strategy: "jwt" }, ...authConfig, // 覆盖Credentials的authorize逻辑 providers: authConfig.providers.map(provider => { if (provider.id === "credentials") { return { ...provider, authorize: async (credentials) => { // 校验输入完整性 if (!credentials?.email || !credentials?.password) { throw new Error("请填写邮箱和密码"); } // 从数据库查询用户 const user = await getUserFromDB(credentials.email); if (!user) { throw new Error("用户不存在"); } // 验证密码(数据库需存储bcrypt哈希后的密码) const isPasswordValid = await bcrypt.compare( credentials.password, user.password ); if (!isPasswordValid) { throw new Error("密码错误"); } // 返回安全的用户信息(排除敏感字段如密码) return { id: user._id.toString(), name: user.name, email: user.email, }; }, }; } return provider; }), // 扩展JWT与Session,传递用户ID callbacks: { async jwt({ token, user }) { if (user) token.id = user.id; return token; }, async session({ session, token }) { if (session.user) session.user.id = token.id; return session; }, }, });
3. 实现数据库查询函数(lib/db-utils.js)
单独封装数据库查询逻辑,便于复用:
// lib/db-utils.js import clientPromise from "./db"; export async function getUserFromDB(email) { const client = await clientPromise; const db = client.db(); // 替换为你的用户集合名称 return db.collection("users").findOne({ email }); }
4. 关键注意事项
- 密码存储:用户注册时必须使用
bcrypt.hash()生成哈希值存入数据库,禁止存储明文密码。示例代码:const hashedPassword = await bcrypt.hash(userInput.password, 10); // 将hashedPassword存入数据库的user文档中 - 环境配置:确保
.env.local中正确配置MONGODB_URI。 - 依赖安装:若未安装bcrypt,执行命令安装:
npm install bcrypt # TypeScript用户需额外安装类型定义 npm install -D @types/bcrypt
内容的提问来源于stack exchange,提问作者Ali Sadain Tanvir
相关产品推荐
相关产品推荐

