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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:43:13