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

Next.js 14服务端渲染时AccessToken过期的RefreshToken刷新方案问询

Next.js 14 App Router 服务端渲染 Token 过期刷新方案

针对你遇到的服务端渲染时 AccessToken 过期、但 RefreshToken Cookie 路径限制导致无法在服务端刷新的问题,以下是几种落地性强的解决方案:

如果可以修改 .NET API 的 Cookie 设置,直接将 RefreshToken 的路径改为根路径 /,这是最简洁的解决方式:

// .NET API 端设置 Cookie 的代码
Response.Cookies.Append("RefreshToken", refreshTokenValue, new CookieOptions
{
    Path = "/", // 修改为根路径
    HttpOnly = true,
    Secure = true,
    SameSite = SameSiteMode.Strict,
    Expires = DateTime.UtcNow.AddDays(7)
});

修改后,Next.js 服务端组件可以直接从请求 Cookie 中获取 RefreshToken,调用 /auth/refresh-token 接口刷新 AccessToken,全程在服务端完成,无需客户端介入,体验最优。

二、服务端预校验 + 客户端刷新兜底

如果无法调整 Cookie 路径,可在服务端组件中先做 Token 有效性校验,失效时返回客户端组件完成刷新,再触发服务端重渲染:

1. 服务端组件(个人资料页)

async function ProfilePage() {
  const accessToken = cookies().get('AccessToken')?.value;
  let isTokenValid = false;

  // 调用轻量的 Token 校验接口(避免请求大体积数据失败)
  try {
    const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/validate-token`, {
      headers: { Authorization: `Bearer ${accessToken}` }
    });
    isTokenValid = res.ok;
  } catch (err) {
    isTokenValid = false;
  }

  // Token 无效时返回客户端刷新组件
  if (!isTokenValid) {
    return <ClientTokenRefresh />;
  }

  // Token 有效时正常请求用户数据并渲染
  const userProfile = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/user/profile`, {
    headers: { Authorization: `Bearer ${accessToken}` }
  }).then(res => res.json());

  return <ProfileContent data={userProfile} />;
}

2. 客户端刷新组件(Client Component)

'use client';

import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import axios from 'axios';

export default function ClientTokenRefresh() {
  const router = useRouter();
  const [refreshFailed, setRefreshFailed] = useState(false);

  useEffect(() => {
    async function refreshAndReload() {
      try {
        // 复用现有 Axios 中间件完成 Token 刷新
        await axios.post('/auth/refresh-token');
        // 刷新成功后触发服务端页面重渲染
        router.refresh();
      } catch (err) {
        setRefreshFailed(true);
      }
    }
    refreshAndReload();
  }, [router]);

  if (refreshFailed) {
    return (
      <div>
        登录状态已过期,请重新登录
        <button onClick={() => router.push('/auth/login')}>去登录</button>
      </div>
    );
  }

  return <div>正在加载...</div>;
}

三、全局 Middleware 拦截方案(优化跳转体验)

通过 Next.js Middleware 拦截所有需鉴权的页面请求,Token 失效时跳转到客户端刷新页面,完成后自动返回原页面:

1. Middleware 代码

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

export async function middleware(request: NextRequest) {
  const accessToken = request.cookies.get('AccessToken')?.value;
  const path = request.nextUrl.pathname;

  // 排除无需鉴权的路径(如登录、刷新页)
  if (path.startsWith('/auth')) {
    return NextResponse.next();
  }

  // 校验 Token 有效性
  let isTokenValid = false;
  try {
    const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/validate-token`, {
      headers: { Authorization: `Bearer ${accessToken}` }
    });
    isTokenValid = res.ok;
  } catch (err) {
    isTokenValid = false;
  }

  // Token 失效时跳转到刷新页,携带原路径参数
  if (!isTokenValid) {
    const redirectUrl = new URL('/auth/refresh-token', request.url);
    redirectUrl.searchParams.set('redirect', path);
    return NextResponse.redirect(redirectUrl);
  }

  return NextResponse.next();
}

// 指定需要鉴权的页面路径
export const config = {
  matcher: ['/profile/:path*', '/dashboard/:path*'],
};

2. 客户端刷新页代码

'use client';

import { useEffect } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import axios from 'axios';

export default function RefreshTokenPage() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const redirectTo = searchParams.get('redirect') || '/';

  useEffect(() => {
    async function refreshAndRedirect() {
      try {
        await axios.post('/auth/refresh-token');
        router.push(redirectTo);
      } catch (err) {
        router.push('/auth/login');
      }
    }
    refreshAndRedirect();
  }, [router, redirectTo]);

  return <div>正在刷新登录状态...</div>;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 12:37:29