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

如何用Next-Auth在Next.js中批量保护多路由免受未授权访问

批量保护Next.js pages目录下learning文件夹页面的几种方法

方法1:封装高阶组件(HOC)

把登录校验逻辑抽成可复用的高阶组件,每个learning页面只需用它包裹,无需重复编写getServerSideProps。

先新建withAuth.js文件:

import { unstable_getServerSession } from "next-auth/next";
import { authOptions } from "../api/auth/[...nextauth]"; // 替换为你的authOptions实际路径

export function withAuth(Component) {
  const AuthComponent = (props) => <Component {...props} />;

  AuthComponent.getServerSideProps = async (context) => {
    const session = await unstable_getServerSession(context.req, context.res, authOptions);
    if (!session) {
      return {
        redirect: {
          destination: "/",
          permanent: false,
        },
      };
    }

    // 兼容原页面自带的getServerSideProps,合并返回结果
    if (Component.getServerSideProps) {
      const componentProps = await Component.getServerSideProps(context);
      return { ...componentProps };
    }

    return { props: {} };
  };

  return AuthComponent;
}

在learning文件夹的页面中使用:

import { withAuth } from "../../withAuth"; // 路径根据实际结构调整

function LearningPage() {
  return <div>学习页面内容</div>;
}

export default withAuth(LearningPage);

方法2:使用Next.js中间件(Middleware)

如果你的Next.js版本是12及以上,推荐用Middleware批量拦截请求,无需修改任何页面代码,是最简洁的批量保护方案。

在项目根目录创建middleware.js文件:

import { unstable_getServerSession } from "next-auth/next";
import { authOptions } from "./pages/api/auth/[...nextauth]"; // 替换为你的authOptions路径
import { NextResponse } from "next/server";

export async function middleware(req) {
  // 匹配learning文件夹下的所有子页面
  if (req.nextUrl.pathname.startsWith("/learning")) {
    const session = await unstable_getServerSession(req, null, authOptions);
    if (!session) {
      // 未登录则重定向到首页
      return NextResponse.redirect(new URL("/", req.url));
    }
  }
  // 已登录或非learning路径,允许正常访问
  return NextResponse.next();
}

// 指定要匹配的路径规则
export const config = {
  matcher: "/learning/:path*",
};

方法3:自定义_app.js的getInitialProps

如果项目使用不支持Middleware的旧版Next.js,可以在_app.js中统一处理登录校验,但需注意该逻辑会影响所有页面,要准确判断路径是否属于learning文件夹。

修改pages/_app.js:

import { unstable_getServerSession } from "next-auth/next";
import { authOptions } from "./api/auth/[...nextauth]"; // 替换为你的authOptions路径
import App from "next/app";

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

MyApp.getInitialProps = async (appContext) => {
  const appProps = await App.getInitialProps(appContext);
  const { req, res } = appContext.ctx;
  
  // 仅对learning路径下的页面做校验
  if (req.url.startsWith("/learning")) {
    const session = await unstable_getServerSession(req, res, authOptions);
    if (!session) {
      res.writeHead(302, { Location: "/" });
      res.end();
      return {};
    }
  }

  return { ...appProps };
};

export default MyApp;

内容的提问来源于stack exchange,提问作者Bilal Mohammad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 11:15:39