You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 23:01:00