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

Next.js如何实现全页面通用的服务端Cookie存在性检测?

可行实现方案

因为你使用的是http-only类型的Cookie,前端JS无法直接读取Cookie值,所以校验逻辑推荐优先在服务端侧执行,以下是两种适配不同场景的成熟方案:


方案1:Next.js中间件(全版本通用,最推荐)

中间件运行在服务端,会在所有页面请求触发前执行,不管是静态生成页面还是服务端渲染页面、用户从任意入口进入站点都能被拦截,完全不需要改动现有业务页面代码。

  1. 在项目根目录(和pages文件夹同级)新建middleware.js文件
  2. 写入如下校验逻辑:
import { NextResponse } from 'next/server'

// 配置不需要登录就能访问的白名单:登录注册页、静态资源、公开接口等
const publicRoutes = [
  '/login',
  '/register',
  '/_next',
  '/favicon.ico',
  '/api/public'
]

export default function middleware(req) {
  const { pathname } = req.nextUrl
  // 白名单路径直接放行
  if (publicRoutes.some(route => pathname.startsWith(route))) {
    return NextResponse.next()
  }

  // 服务端直接读取请求头中的Cookie,判断认证token是否存在
  const authToken = req.cookies.get('auth_token')?.value
  if (!authToken) {
    // 未登录则跳转到登录页,带上当前页面路径作为登录后的回调参数
    const loginUrl = new URL('/login', req.url)
    loginUrl.searchParams.set('redirect', req.nextUrl.pathname + req.nextUrl.search)
    return NextResponse.redirect(loginUrl)
  }

  // 校验通过,继续正常请求
  return NextResponse.next()
}

// 配置中间件生效范围,匹配全站所有路径
export const config = {
  matcher: '/:path*',
}

注意:上述逻辑仅判断Cookie是否存在,如果需要校验token有效性、是否过期,可在中间件中向后端认证接口发起请求,携带当前Cookie完成校验后再放行,避免无效token通行。


方案2:Pages Router场景下修复_app.js的getInitialProps逻辑

你之前用getInitialProps不生效大概率是因为项目中存在使用getStaticProps的静态生成页面,这类页面的服务端请求默认不会触发_app的getInitialProps,可以配合客户端路由拦截逻辑补全覆盖:

import App from 'next/app'
import { useRouter } from 'next/router'
import { useEffect } from 'react'

const publicRoutes = ['/login', '/register', '/about']

function MyApp({ Component, pageProps, isAuthenticated }) {
  const router = useRouter()

  // 客户端侧路由跳转时的校验逻辑,覆盖静态页跳转场景
  useEffect(() => {
    const handleRouteChange = async (url) => {
      if (publicRoutes.includes(url)) return
      // 调用后端轻量校验接口,请求会自动携带http-only Cookie,返回登录状态
      const res = await fetch('/api/auth/check')
      if (!res.ok) {
        router.push('/login?redirect=' + encodeURIComponent(router.asPath))
      }
    }
    router.events.on('routeChangeStart', handleRouteChange)
    return () => router.events.off('routeChangeStart', handleRouteChange)
  }, [router])

  if (!isAuthenticated && !publicRoutes.includes(router.pathname)) {
    router.push('/login?redirect=' + encodeURIComponent(router.asPath))
    return null
  }

  return <Component {...pageProps} />
}

// 服务端侧校验逻辑,覆盖动态页面首屏请求
MyApp.getInitialProps = async (appContext) => {
  const appProps = await App.getInitialProps(appContext)
  const { req, res } = appContext.ctx
  let isAuthenticated = false

  if (req) {
    const cookies = req.headers.cookie || ''
    isAuthenticated = cookies.includes('auth_token=')
    if (!isAuthenticated && !publicRoutes.includes(appContext.ctx.pathname)) {
      res?.writeHead(302, {
        Location: `/login?redirect=${encodeURIComponent(appContext.ctx.asPath)}`
      })
      res?.end()
      return { ...appProps, isAuthenticated: false }
    }
  }

  return { ...appProps, isAuthenticated }
}

export default MyApp

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 18:27:04