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

Next.js:如何用正则将动态Post URL加入protectedRoutes数组?

Next.js 动态路由权限控制解决方案

我在开发带认证功能的Next.js项目,目前将需要保护的URL以字符串形式存入protectedRoutes数组,未登录用户访问这些路由会被重定向。现在需要把所有/post/[postId]格式的动态帖子页面加入保护,但直接添加正则表达式无效,也不想遍历Firebase中的所有帖子ID逐个添加(避免数组过长影响搜索效率)。

尝试过的无效代码

const postURL = new RegExp("/post/")
const protectedRoutes = ["/home", "/profile", postURL];

希望避免的写法

const postID = getPostID() // 从Firebase获取帖子ID的函数

postID.forEach((id) => {
  protectedRoutes.push(`/post/${id}`);
});

现有项目代码

_app.js

import PrivateRoute from "@/components/PrivateRoute";
import { AuthProvider } from "@/contexts/AuthContext";
import "@/styles/globals.css";

export default function App({ Component, pageProps }) {
  const protectedRoutes = ["/home", "/profile"];
  const publicRoutes = [
    "/",
    "/sign-in",
    "/sign-in/phone",
    "/sign-up",
    "/reset-password",
  ];

  return (
    <AuthProvider>
      <PrivateRoute
        protectedRoutes={protectedRoutes}
        publicRoutes={publicRoutes}
      >
        <Component {...pageProps} />
      </PrivateRoute>
    </AuthProvider>
  );
}

PrivateRoute.jsx

import { useEffect } from "react";
import { useRouter } from "next/router";

import { useAuth } from "@/contexts/AuthContext";
import FullPageLoader from "./FullPageLoader";

export default function PrivateRoute({
  protectedRoutes,
  publicRoutes,
  children,
}) {
  const router = useRouter();
  const { currentUser, loading } = useAuth();

  const pathIsProtected = protectedRoutes.indexOf(router.pathname) !== -1;
  const pathIsPublic = publicRoutes.indexOf(router.pathname) !== -1;

  useEffect(() => {
    if (!loading && !currentUser && pathIsProtected) {
      router.push("/sign-in");
    }

    if (!loading && currentUser && pathIsPublic) {
      router.push("/home");
    }
  }, [currentUser, loading, pathIsProtected, pathIsPublic]);

  if ((loading || !currentUser) && pathIsProtected) {
    return <FullPageLoader />;
  }

  if ((loading || currentUser) && pathIsPublic) {
    return <FullPageLoader />;
  }

  return children;
}

解决方案

方案一:修改全局权限判断逻辑,支持正则匹配

核心思路是让protectedRoutes数组同时支持字符串和正则表达式,然后修改判断逻辑,分别处理两种类型的路由规则。

  1. 更新_app.js中的路由规则
    在protectedRoutes中加入匹配所有帖子路径的正则:
const protectedRoutes = ["/home", "/profile", /^\/post\/.+$/];

正则/^\/post\/.+$/表示匹配以/post/开头、后面包含任意字符的路径,覆盖所有/post/[postId]格式的动态路由。

  1. 修改PrivateRoute中的判断逻辑
    替换原来的indexOf判断,改用some方法遍历规则,区分字符串和正则的匹配方式:
// 替换原有的pathIsProtected判断
const pathIsProtected = protectedRoutes.some(route => {
  if (typeof route === 'string') {
    return router.pathname === route;
  } else if (route instanceof RegExp) {
    return route.test(router.pathname);
  }
  return false;
});

// 若publicRoutes未来也需要支持动态规则,可同步修改pathIsPublic
const pathIsPublic = publicRoutes.some(route => {
  if (typeof route === 'string') {
    return router.pathname === route;
  } else if (route instanceof RegExp) {
    return route.test(router.pathname);
  }
  return false;
});

这样既不用维护海量的帖子ID路由,又能高效匹配所有动态帖子路径,代码改动小且逻辑统一。

方案二:页面级单独验证(可选补充)

如果需要对单个帖子页面做更精细的权限控制(比如部分帖子允许未登录查看),可以直接在/post/[postId].js页面中添加认证逻辑:

import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { useAuth } from '@/contexts/AuthContext';
import FullPageLoader from '../components/FullPageLoader';

export default function PostPage({ postData }) {
  const router = useRouter();
  const { currentUser, loading } = useAuth();

  useEffect(() => {
    if (!loading && !currentUser) {
      router.push('/sign-in');
    }
  }, [currentUser, loading]);

  if (loading || !currentUser) {
    return <FullPageLoader />;
  }

  return <div>{postData.content}</div>;
}

// 若使用SSR,可在getServerSideProps中提前验证(推荐)
export async function getServerSideProps(context) {
  // 从请求中获取认证状态(比如cookie中的session)
  const session = await getSession(context);
  if (!session) {
    return {
      redirect: {
        destination: '/sign-in',
        permanent: false,
      },
    };
  }

  // 获取对应帖子数据
  const postData = await fetchPost(context.params.postId);
  return {
    props: { postData },
  };
}

这种方式适合特殊场景下的权限定制,全局控制还是推荐方案一。


内容的提问来源于stack exchange,提问作者Lauris Kwan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 00:52:48