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

Next.js+React项目中如何禁止用户直接通过URL访问指定路由?

限制Next.js中/checkout系列路由的直接访问方法

方案1:通过会话状态追踪导航流程

核心思路是给用户会话标记「是否完成前置导航步骤」,只有当用户从允许的页面(比如购物车页)跳转过来时,才放行访问/checkout或/checkout/success。

以Pages Router为例:

  1. 在购物车页面(/cart)添加状态标记,用户进入时在Cookie或localStorage存入标识:
// pages/cart.js
import { useEffect } from 'react';

export default function Cart() {
  useEffect(() => {
    // 用Cookie更适合服务端校验,避免localStorage的跨标签页问题
    document.cookie = "allowedCheckout=true; path=/; max-age=3600";
  }, []);

  return <div>购物车页面</div>;
}
  1. 在/checkout页面通过服务端函数校验标识,不满足则重定向:
// pages/checkout.js
export async function getServerSideProps(context) {
  const allowed = context.req.cookies.allowedCheckout === 'true';
  if (!allowed) {
    return {
      redirect: {
        destination: '/cart',
        permanent: false,
      },
    };
  }
  // 校验通过后清除标识,防止重复利用
  context.res.setHeader('Set-Cookie', 'allowedCheckout=; Path=/; Max-Age=0');
  return { props: {} };
}

export default function Checkout() {
  return <div>结算页面</div>;
}

如果用App Router(Next.js 13+),可以在Server Component中用cookies()函数做校验,逻辑和上面一致。

方案2:用Next.js中间件拦截非法请求

通过中间件拦截所有/checkout开头的路由,检查请求的Referer头,判断是否来自站内的前置页面。注意:Referer可能被浏览器隐私策略禁用,建议和方案1结合使用。

// middleware.js
import { NextResponse } from 'next/server';

export function middleware(request) {
  const path = request.nextUrl.pathname;
  if (path.startsWith('/checkout')) {
    const referer = request.headers.get('referer');
    // 校验来源是否为本站的购物车页面
    if (!referer || !referer.includes(`${request.nextUrl.origin}/cart`)) {
      return NextResponse.redirect(new URL('/cart', request.nextUrl));
    }
  }
  return NextResponse.next();
}

export const config = {
  matcher: ['/checkout/:path*'],
};

方案3:客户端路由跳转时传递校验状态

使用next/link或useRouter跳转时,通过state传递校验信息,在/checkout页面检查状态是否存在:

// 购物车页面的跳转代码
import Link from 'next/link';

<Link 
  href="/checkout" 
  state={{ allowed: true }}
>
  前往结算
</Link>

// pages/checkout.js的客户端校验
import { useRouter } from 'next/router';
import { useEffect } from 'react';

export default function Checkout() {
  const router = useRouter();

  useEffect(() => {
    // 直接访问时state不存在,触发重定向
    if (!router.state?.allowed) {
      router.push('/cart');
    }
  }, [router]);

  return <div>结算页面</div>;
}

⚠️ 注意:客户端校验可以被篡改绕过,优先选择服务端校验方式(方案1的getServerSideProps或方案2的中间件)。

/checkout/success的额外处理

这个页面是支付完成后的回调页,除了前置导航校验,还要确保用户确实发起过支付请求:

  • 发起支付时生成唯一订单ID并存入会话
  • 在success页面校验订单ID的有效性,同时检查请求来源是否为支付网关或/checkout页面

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 02:52:42