在Next.js中基于多NextAuth实例实现跨端口认证与重定向管控
解决方案
1. 全局拦截所有者页面访问,重定向客户端用户
用Next.js的Middleware实现全局访问控制,只要检测到客户端身份的用户访问所有者页面,直接跳转到3000端口的客户端应用。
创建所有者应用的middleware.js文件:
import { getServerSession } from "next-auth/next"; import { authOptions } from "./pages/api/auth/[...nextauth]"; import { NextResponse } from "next/server"; export async function middleware(req) { const session = await getServerSession(req, req.nextUrl, authOptions); // 已登录且为客户端用户,强制重定向到客户端应用 if (session?.user?.role === "client") { return NextResponse.redirect(new URL("http://localhost:3000", req.url)); } // 未登录用户直接引导到客户端登录页 if (!session) { return NextResponse.redirect(new URL("http://localhost:3000/login", req.url)); } return NextResponse.next(); } // 指定需要保护的所有者页面路径,替换成你的实际路径 export const config = { matcher: ["/owner/**", "/admin/**"], };
2. 自定义登录页与登录回调控制
配置所有者应用的NextAuth
修改所有者应用的pages/api/auth/[...nextauth].js,加入自定义登录页配置和角色判断的重定向逻辑:
import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; // 替换成你的凭证验证服务 async function validateCredentials(credentials) { // 这里调用你的认证接口,返回包含role字段的用户信息 const user = await fetch("your-auth-api-url", { method: "POST", body: JSON.stringify(credentials), headers: { "Content-Type": "application/json" }, }).then(res => res.json()); return user; } export const authOptions = { // 指定自定义登录页路径 pages: { signIn: "/login", }, providers: [ CredentialsProvider({ name: "Credentials", credentials: { email: { label: "Email", type: "email" }, password: { label: "Password", type: "password" }, }, async authorize(credentials) { const user = await validateCredentials(credentials); // 验证通过返回用户,否则返回null return user ?? null; }, }), ], callbacks: { // 将角色存入JWT async jwt({ token, user }) { if (user) token.role = user.role; return token; }, // 将角色同步到session async session({ session, token }) { session.user.role = token.role; return session; }, // 登录完成后根据角色控制重定向 async redirect({ url, baseUrl }) { const session = await getServerSession(authOptions); if (session?.user?.role === "client") { // 客户端用户直接跳转到3000端口 return "http://localhost:3000"; } // 所有者用户正常返回原页面或应用根路径 return url.startsWith(baseUrl) ? url : baseUrl; }, }, }; export default NextAuth(authOptions);
自定义登录页实现
在所有者应用的pages/login.js中,添加逻辑自动引导用户到客户端登录页:
import { getServerSession } from "next-auth/next"; import { authOptions } from "./api/auth/[...nextauth]"; import { useEffect } from "react"; import { useRouter } from "next/router"; export async function getServerSideProps(context) { const session = await getServerSession(context.req, context.res, authOptions); if (session?.user?.role === "client") { return { redirect: { destination: "http://localhost:3000", permanent: false, }, }; } return { props: {} }; } export default function Login() { const router = useRouter(); useEffect(() => { // 自动跳转到客户端登录页 router.push("http://localhost:3000/login"); }, [router]); return ( <div> <p>正在跳转到客户端登录页...</p> </div> ); }
3. 客户端应用的登录页配置
客户端应用的NextAuth同样需要配置自定义登录页,确保登录流程在3000端口完成:
// client-app/pages/api/auth/[...nextauth].js import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; export const authOptions = { pages: { signIn: "/login", }, // 其他认证配置(凭证验证、回调逻辑等) }; export default NextAuth(authOptions);
内容的提问来源于stack exchange,提问作者khadir salim
相关产品推荐
相关产品推荐

