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

Next.js 13.4如何利用Redux Toolkit存储的Token实现路由保护?

解决方案:Next.js 中结合 Token 实现路由保护(无法读取 Redux 数据的处理)

首先明确核心问题:Next.js 的 middleware.js 运行在边缘/服务器端,而 Redux 状态是存储在客户端浏览器内存中的,两者运行环境完全隔离,因此无法直接在 Middleware 中读取 Redux 数据。下面是几种可行的解决思路:

1. 首选方案:将 Token 存入 Cookie,在 Middleware 中读取验证

这是最符合 Next.js 架构且安全的方式,因为 Middleware 可以直接读取请求 Cookie。

登录接口返回 Token 后,除了存入 Redux,同时将 Token 写入 HttpOnly、Secure 类型的 Cookie(生产环境下开启 Secure,防止非 HTTPS 传输):

// 客户端登录逻辑(比如登录页面的提交函数)
import { useDispatch } from 'react-redux';
import { setToken } from '@/redux/slices/authSlice';

async function handleLogin(formData) {
  const res = await fetch('/api/login', {
    method: 'POST',
    body: formData
  });
  const { token } = await res.json();

  // 存入 Redux
  const dispatch = useDispatch();
  dispatch(setToken(token));

  // 写入 Cookie
  document.cookie = `authToken=${token}; path=/; secure=${process.env.NODE_ENV === 'production'}; httpOnly=true; SameSite=Strict`;
}

注:HttpOnly Cookie 无法被前端 JS 读取,能有效防止 XSS 攻击,适合存储认证 Token。

步骤2:在 Middleware 中拦截并验证 Token

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

export function middleware(request: NextRequest) {
  // 读取 Cookie 中的 Token
  const token = request.cookies.get('authToken')?.value;
  // 定义需要保护的路由
  const protectedRoutes = ['/dashboard', '/profile', '/orders'];
  
  // 检查当前请求是否访问受保护路由,且无有效 Token
  const isAccessingProtectedRoute = protectedRoutes.some(route => 
    request.nextUrl.pathname.startsWith(route)
  );

  if (isAccessingProtectedRoute && !token) {
    // 重定向到登录页,同时记录原路径方便登录后跳转
    const loginUrl = new URL('/login', request.url);
    loginUrl.searchParams.set('redirect', request.nextUrl.pathname);
    return NextResponse.redirect(loginUrl);
  }

  // 有有效 Token,允许继续访问
  return NextResponse.next();
}

// 指定 Middleware 生效的路由范围
export const config = {
  matcher: ['/dashboard/:path*', '/profile/:path*', '/orders/:path*'],
};

2. 客户端路由保护(作为补充方案)

如果场景限制无法使用 Cookie,可在客户端组件中结合 Redux 做路由拦截,但注意这种方式只能做前端层面的保护,无法阻止用户直接访问页面(页面会先加载再跳转),建议配合服务端验证。

实现客户端路由保护组件

'use client';
import { useEffect } from 'react';
import { useSelector } from 'react-redux';
import { usePathname, useRouter } from 'next/navigation';

export default function ProtectedRoute({ children }) {
  const token = useSelector(state => state.auth.token);
  const pathname = usePathname();
  const router = useRouter();
  const protectedPaths = ['/dashboard', '/profile', '/orders'];

  useEffect(() => {
    const needsProtection = protectedPaths.some(path => pathname.startsWith(path));
    if (needsProtection && !token) {
      router.push(`/login?redirect=${pathname}`);
    }
  }, [token, pathname, router]);

  // 未登录时可返回加载态或空
  if (!token) return <div>Loading...</div>;
  
  return children;
}

在受保护页面中使用该组件

// app/dashboard/page.js
import ProtectedRoute from '@/components/ProtectedRoute';

export default function DashboardPage() {
  return (
    <ProtectedRoute>
      <div>你的仪表盘内容</div>
    </ProtectedRoute>
  );
}

3. Server Component 服务端验证(App Router)

对于 App Router 的 Server Component,可以直接读取 Cookie 并验证 Token 有效性,无效则重定向:

// app/orders/page.js
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';

export default async function OrdersPage() {
  const token = cookies().get('authToken')?.value;

  // 调用后端接口验证 Token 有效性
  const isValidToken = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/verify-token`, {
    headers: { Authorization: `Bearer ${token}` }
  }).then(res => res.ok);

  if (!token || !isValidToken) {
    redirect('/login');
  }

  // 验证通过,渲染页面内容
  return <div>你的订单列表</div>;
}

内容的提问来源于stack exchange,提问作者Prem sagar Vishwakarma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:42:30