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

Next.js子域名部署场景下API路由及NextAuth配置方法

子域名Next.js应用API路由与NextAuth适配方案

目录结构调整

Next.js 强制API路由必须位于pages/api目录下,通过路径划分+中间体重写即可实现主/子域名API隔离,调整后的pages目录结构如下:

  • /pages/api:主域名domain.com专属API路由,原有主域名逻辑保持不变
  • /pages/api/subdomain:子域名subdomain.domain.com专属API路由,所有子域名接口、NextAuth路由全部放在该目录下
  • /pages/subdomain_logic:原有子域名页面逻辑目录,保持不变
  • 其余主域名页面、全局配置文件(_app.tsx等)保持原有结构

Middleware 逻辑修正

原有中间件存在两个问题:matcher规则未覆盖API路径、子域名重写逻辑未处理/api开头的请求,修正后代码如下:

import { NextRequest, NextResponse } from "next/server";

export const config = {
  matcher: [
    "/",
    "/([^/.]*)",
    "/api/:path*", // 新增API路径匹配
    "/site/:path*",
    "/post/:path*",
    "/_sites/:path*"
  ]
};

export default function middleware(req: NextRequest) {
  const url = req.nextUrl;
  const pathname = url.pathname;
  const hostname = req.headers.get("host");

  if (!hostname)
    return new Response(null, {
      status: 400,
      statusText: "No hostname found in request headers"
    });

  const currentHost =
    process.env.VERCEL_ENV === "production" ||
    process.env.VERCEL_ENV === "preview"
      ? hostname
          .replace(`.domain.com`, "")
          .replace(`${process.env.VERCEL_URL}`, "")
          .replace(`${process.env.NEXT_PUBLIC_VERCEL_URL}`, "")
      : hostname.replace(`.localhost:3000`, "");

  if (pathname.startsWith(`/_sites`))
    return new Response(null, { status: 404 });

  if (!pathname.includes(".")) {
    if (currentHost === "subdomain") {
      // 已登录用户访问登录页直接跳首页
      if (
        pathname === "/login" &&
        (req.cookies.get("next-auth.session-token") ||
          req.cookies.get("__Secure-next-auth.session-token"))
      ) {
        url.pathname = "/";
        return NextResponse.redirect(url);
      }

      // 子域名API请求重写到专属api/subdomain路径
      if (pathname.startsWith("/api")) {
        url.pathname = `/api/subdomain${pathname.replace(/^\/api/, "")}`;
        return NextResponse.rewrite(url);
      }

      // 子域名页面请求重写到subdomain_logic对应路径
      url.pathname = `/subdomain_logic${pathname}`;
      return NextResponse.rewrite(url);
    }
    // 主域名请求保持原有路径
    return NextResponse.rewrite(url);
  }
}

注意:原有代码中子域名页面路径重写写的是/subdomain,和描述的实际目录名subdomain_logic不一致,已修正为对应目录名;同时修正了新版本Next.js中cookies的读取方式,避免运行报错。

NextAuth 适配配置

  1. 路由文件位置:将NextAuth动态路由文件放在pages/api/subdomain/auth/[...nextauth].ts路径下,和子域名其他API保持同目录。
  2. 核心配置项参考:
import NextAuth from "next-auth";
// 按需引入你使用的认证provider
import GithubProvider from "next-auth/providers/github";

export default NextAuth({
  providers: [
    // 替换为你实际使用的认证服务商配置
    GithubProvider({
      clientId: process.env.GITHUB_ID!,
      clientSecret: process.env.GITHUB_SECRET!,
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
  cookies: {
    sessionToken: {
      name:
        process.env.NODE_ENV === "production"
          ? "__Secure-next-auth.session-token"
          : "next-auth.session-token",
      options: {
        // 需要和主域名共享会话则domain设为`.domain.com`(前面带点);需要隔离会话则设为`subdomain.domain.com`
        domain: process.env.NODE_ENV === "production" ? ".domain.com" : undefined,
        httpOnly: true,
        sameSite: "lax",
        path: "/",
        secure: process.env.NODE_ENV === "production",
      },
    },
  },
  pages: {
    signIn: "/login",
  },
  // 其余回调、权限配置按需设置即可
});
  1. 环境变量配置:
  • 本地开发:NEXTAUTH_URL=http://subdomain.localhost:3000
  • 生产环境:NEXTAUTH_URL=https://subdomain.domain.com

验证规则

  • 主域名domain.com/api/*请求正常走主域名原有API逻辑,完全不受子域名配置影响
  • 子域名subdomain.domain.com/api/*请求会被中间件自动重写到/api/subdomain/*路径,和主域名API完全隔离
  • 子域名下NextAuth登录、会话校验、回调逻辑全部正常生效,调整cookie.domain配置即可实现主/子域名会话共享或隔离

内容的提问来源于stack exchange,提问作者Nicolás Guasca Santamaría

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 22:27:23