如何在Next.js项目中对接已有Node+Express后端使用NextAuth?
自定义Node后端返回Token时的NextAuth身份验证实现
原场景:Next项目内直连数据库的NextAuth配置
以下是api/auth/[...nextauth]/route.ts中直连数据库的典型配置:
import { connectDB } from "@/libs/mongodb"; import User from "@/models/user"; import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; import bcrypt from "bcryptjs"; const handler = NextAuth({ providers: [ CredentialsProvider({ name: "Credentials", id: "credentials", credentials: { email: { label: "Email", type: "text", placeholder: "jsmith" }, password: { label: "Password", type: "password" }, }, async authorize(credentials) { await connectDB(); const userFound = await User.findOne({ email: credentials?.email, }).select("+password"); if (!userFound) throw new Error("Invalid credentials"); const passwordMatch = await bcrypt.compare( credentials!.password, userFound.password ); if (!passwordMatch) throw new Error("Invalid credentials"); console.log(userFound); return userFound; }, }), ], pages: { signIn: "/login", }, session: { strategy: "jwt", }, callbacks: { async jwt({ token, user }) { if (user) token.user = user; return token; }, async session({ session, token }) { session.user = token.user as any; return session; }, }, }); export { handler as GET, handler as POST };
对接返回Token的自定义Node后端实现方案
如果你的自定义Node后端在登录/认证流程中返回JWT Token,可按以下步骤修改NextAuth配置:
1. 调整CredentialsProvider的验证逻辑
不再直连数据库,改为调用后端登录接口验证用户凭证,获取Token和用户信息:
import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; const handler = NextAuth({ providers: [ CredentialsProvider({ name: "Credentials", credentials: { email: { label: "Email", type: "text" }, password: { label: "Password", type: "password" }, }, async authorize(credentials) { // 调用自定义Node后端的登录接口 const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/login`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ email: credentials?.email, password: credentials?.password, }), }); const data = await response.json(); // 验证接口返回状态,失败则抛出错误 if (!response.ok || !data.token) { throw new Error(data.message || "登录失败"); } // 返回用户信息和后端返回的Token return { id: data.user.id, name: data.user.name, email: data.user.email, token: data.token, }; }, }), ], pages: { signIn: "/login", }, session: { strategy: "jwt", // 保持JWT策略,存储自定义Token }, callbacks: { // 在JWT中存储后端返回的Token和用户信息 async jwt({ token, user }) { if (user) { token.user = { id: user.id, name: user.name, email: user.email, }; token.accessToken = user.token; // 存储后端的JWT Token } return token; }, // 将Token和用户信息注入到session中,供前端使用 async session({ session, token }) { session.user = token.user as any; session.accessToken = token.accessToken as string; return session; }, }, // 配置JWT加密密钥,需与.env中的NEXTAUTH_SECRET保持一致 secret: process.env.NEXTAUTH_SECRET, }); export { handler as GET, handler as POST };
2. 前端使用验证逻辑
在前端组件中,通过useSession钩子获取accessToken,调用后端接口时携带该Token:
import { useSession } from "next-auth/react"; const ProfilePage = () => { const { data: session } = useSession(); const fetchUserProfile = async () => { const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/user/profile`, { headers: { Authorization: `Bearer ${session?.accessToken}`, }, }); const profile = await response.json(); // 处理用户信息 }; return <div>用户页面</div>; }; export default ProfilePage;
3. 自定义Node后端的Token验证示例
后端需要验证前端传来的Token,确保请求合法性:
const jwt = require("jsonwebtoken"); const authenticateToken = (req, res, next) => { const authHeader = req.headers["authorization"]; const token = authHeader && authHeader.split(" ")[1]; if (!token) { return res.status(401).json({ message: "未提供Token" }); } jwt.verify(token, process.env.JWT_SECRET, (err, user) => { if (err) { return res.status(403).json({ message: "无效的Token" }); } req.user = user; next(); }); }; // 受保护的路由示例 app.get("/user/profile", authenticateToken, (req, res) => { res.json({ user: req.user }); });
内容的提问来源于stack exchange,提问作者Enzo Barrera
相关产品推荐
相关产品推荐

