背景
因为升级到了Next-auth:5.0,鉴权结构变了,middleware的代码如下:
import { auth as middleware } from "@/lib/auth";export const config = {matcher: `/admin/:path*`,// 不是管理员就跳转到主页};export default middleware;
其中auth文件如下:
import NextAuth from "next-auth";import Credentials from "next-auth/providers/credentials";import GithubProvider from "next-auth/providers/github";import { PrismaAdapter } from "@auth/prisma-adapter";import { NODE_ENV } from "@/config";import { PATHS } from "@/constants";import { getUserByEmailAndPassword } from "@/features/auth";import { prisma } from "./prisma";import { isAdmin, myLog } from "./utils";export const runtime = "nodejs";export const { handlers, auth, signOut, signIn } = NextAuth({adapter: PrismaAdapter(prisma),providers: [GithubProvider,Credentials({// You can specify which fields should be submitted, by adding keys to the `credentials` object.// e.g. domain, username, password, 2FA token, etc.credentials: {email: { label: "email", type: "email" },password: { label: "password", type: "password" },},authorize: async (credentials) => {try {// 避免在这里直接打印 credentialsconst { email, password } = credentials as {email: string;password: string;};// myLog("credentials", JSON.stringify(credentials));const user = await getUserByEmailAndPassword(email, password);// myLog("user", JSON.stringify(user));return {id: user.id,email: user.email,name: user.name,};} catch (error) {return null;}},}),],// 解决这个错误:Error: PrismaClient is not configured to run in Vercel Edge Functions or Edge Middleware.// 参考:https://github.com/prisma/prisma/issues/21310#issuecomment-1840428931session: { strategy: "jwt" },trustHost: true,pages: {signIn: PATHS.AUTH_SIGN_IN,},debug: NODE_ENV === "development",callbacks: {// signinasync signIn({ user }) {// myLog("signIn", user);// 模拟promisereturn new Promise((resolve) => resolve(true));},session({ session, token }) {myLog("session", session, token);if (session.user && token?.sub) {session.user.id = token.sub;}return session;},authorized({ request, auth }) {myLog("authorized", request, auth);// 将来用作 Next.js middleware,如果是访问后台页面,校验是否登录if (request.nextUrl.pathname.startsWith(PATHS.ADMIN_HOME)) {// 是否是管理员if (!isAdmin(auth?.user?.email)) {return Response.redirect(new URL(PATHS.SITE_HOME, request.url));} else {return true;}}// 其它路径直接放行return true;},},});
然后因为getUserByEmailAndPassword这个方法里有用到redis,就导致报错了····
这让我很是疑惑啊,middleware 是一个中间件,只能用于EdgeRuntime,但是EdgeRuntime不能够使用io-redis,怎么办呢?
解决方式
绕过middleware中间件
新建文件
参考:https://stackoverflow.com/questions/78713102/using-redis-with-auth-js-and-next-js-middleware-on-edge-runtime-dns-module-er我们可以在 Next.js 的 Edge 运行时使用数据库函数吗?当然可以,但也不能直接使用。我找到了一个解决方案,一种方法是创建一个 API 路由处理程序,并在 Edge 运行时使用 fetch 来实现。
在 auth.js 中,您可以创建一个独立的 auth.config.ts 文件(该文件不会执行任何边缘运行时不支持的数据库操作) 官方解释:
https://authjs.dev/guides/edge-compatibility#the-solution
关于在middleware里拿不到数据:
参考issue:https://github.com/nextauthjs/next-auth/issues/9836

