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

缺少httpOnly cookie时如何用React HOC实现受保护页面的服务端重定向

可行方案整理

方案1:使用Next.js Middleware(最优解,不破坏静态优化)

Next.js 12及以上版本提供的Middleware能力可以完美匹配你的需求:

  • 运行在服务端Edge节点,在请求到达你的页面资源(不管是静态优化页还是SSR页)之前就执行
  • 支持直接读取请求携带的httpOnly Cookie,不需要在客户端执行任何逻辑
  • 完全不会影响应用的自动静态优化能力,静态生成的页面依然可以保留所有性能优势
  • 只需要编写一次逻辑,全局生效,不需要修改任何页面代码

你可以在项目根目录(或src目录下)新建middleware.ts文件,示例代码如下:

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

// 定义需要鉴权的路由前缀,可根据实际需求调整
const PROTECTED_ROUTES = ['/dashboard', '/user', '/settings']

export function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl
  // 校验当前请求路径是否属于受保护路由
  const isProtectedRoute = PROTECTED_ROUTES.some(route => pathname.startsWith(route))
  
  if (isProtectedRoute) {
    // 读取你用于鉴权的refresh token的cookie,替换成你实际的cookie名
    const refreshToken = request.cookies.get('refresh_token')?.value
    
    if (!refreshToken) {
      // 未携带有效鉴权cookie,直接在服务端重定向到登录页
      return NextResponse.redirect(new URL('/auth/login', request.url))
    }

    // 如果你需要严格校验token有效性,也可以在这里调用你的/api/user接口校验,校验不通过同样重定向
  }

  return NextResponse.next()
}

你原来写的客户端withAuth HOC可以保留作为二次校验,避免极端场景下绕过中间件的情况。

方案2:App Router 路由组+全局Layout(如果你使用Next.js 13+ App Router)

如果你已经切换到App Router模式,可以把所有受保护的页面放在同一个路由组下,比如(protected),然后在路由组的layout.tsx中编写一次服务端鉴权逻辑即可,所有子页面都会继承这个逻辑,不需要单独编写:

// app/(protected)/layout.tsx
import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'

export default function ProtectedLayout({
  children,
}: {
  children: React.ReactNode
}) {
  const refreshToken = cookies().get('refresh_token')?.value
  if (!refreshToken) {
    redirect('/auth/login')
  }
  return <>{children}</>
}

方案3:封装通用getServerSideProps高阶函数

如果你确实需要使用getServerSideProps的能力,可以封装一个通用的高阶函数,避免每个页面重复编写逻辑:

import type { GetServerSideProps, GetServerSidePropsContext } from 'next'

export function withAuthSSP<T extends { [key: string]: any }>(
  getServerSideProps?: GetServerSideProps<T>
): GetServerSideProps<T> {
  return async (ctx: GetServerSidePropsContext) => {
    const refreshToken = ctx.req.cookies.refresh_token
    if (!refreshToken) {
      return {
        redirect: {
          destination: '/auth/login',
          permanent: false,
        },
      }
    }
    // 如果页面有自定义的getServerSideProps逻辑就执行,否则返回空props
    if (getServerSideProps) {
      return getServerSideProps(ctx)
    }
    return { props: {} as T }
  }
}

使用时只需要在受保护页面导出包装后的方法即可:

// 页面不需要写任何鉴权逻辑,直接导出包装后的getServerSideProps
export const getServerSideProps = withAuthSSP()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 06:06:07