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

Next.js 13中Middleware结合AuthContext实现未登录跳转报错求助

解决Next.js 13 Middleware中使用useContext的报错问题

错误原因

Middleware 运行在React组件树之外(属于边缘/服务器端执行环境),而useContext是React专属Hook,仅能在React组件或自定义Hook内部调用,直接在Middleware中使用必然触发TypeError。

正确解决方案

要在Middleware中判断用户登录状态,不能依赖客户端的AuthContext,必须通过服务端可读取的标识(如Cookie)来验证,具体步骤如下:

1. 登录成功后将状态存入Cookie

在登录逻辑(比如AuthContext的登录函数)中,验证用户身份后,设置一个HttpOnly Cookie标记登录状态:

// 在AuthContext的login函数中添加Cookie设置逻辑
import { cookies } from 'next/headers';

const login = async (credentials) => {
  const res = await fetch('/api/login', {
    method: 'POST',
    body: JSON.stringify(credentials),
  });
  const user = await res.json();
  
  if (res.ok) {
    // 设置HttpOnly Cookie,服务端可读取
    cookies().set('auth_token', user.token, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'strict',
      maxAge: 60 * 60 * 24 * 7, // 有效期7天
      path: '/',
    });
    // 更新AuthContext的客户端状态
    setUser(user);
  }
};

2. 在Middleware中读取Cookie验证登录

修改middleware.js,通过读取Cookie判断登录状态,替代useContext:

import { NextResponse } from 'next/server';
import { cookies } from 'next/headers';

export function middleware(request) {
  // 读取登录状态Cookie
  const authToken = cookies().get('auth_token')?.value;
  
  // 定义需要保护的路由(根据实际需求调整)
  const protectedRoutes = ['/dashboard', '/profile'];
  const isProtectedRoute = protectedRoutes.some(route => request.nextUrl.pathname.startsWith(route));
  
  // 登录页路由
  const loginUrl = new URL('/login', request.nextUrl.origin);
  
  // 未登录访问受保护路由,重定向到登录页(记录原路径)
  if (isProtectedRoute && !authToken) {
    loginUrl.searchParams.set('redirect', request.nextUrl.pathname);
    return NextResponse.redirect(loginUrl);
  }
  
  // 已登录访问登录页,重定向到主页或原路径
  if (request.nextUrl.pathname === '/login' && authToken) {
    const redirectUrl = request.nextUrl.searchParams.get('redirect') || '/';
    return NextResponse.redirect(new URL(redirectUrl, request.nextUrl.origin));
  }
  
  // 其他情况正常放行
  return NextResponse.next();
}

// 指定Middleware生效的路由(可选,也可在逻辑内判断)
export const config = {
  matcher: ['/login', '/dashboard/:path*', '/profile/:path*'],
};

3. 同步AuthContext与Cookie状态

在AuthContext初始化时,读取Cookie恢复用户状态,确保客户端与服务端状态一致:

// context/AuthContext.js
'use client';
import { createContext, useContext, useState, useEffect } from 'react';
import { cookies } from 'next/headers';

const AuthContext = createContext();

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  
  useEffect(() => {
    const authToken = cookies().get('auth_token')?.value;
    if (authToken) {
      // 调用接口验证token并获取用户信息
      fetch('/api/me', {
        headers: {
          Authorization: `Bearer ${authToken}`,
        },
      })
      .then(res => res.json())
      .then(userData => setUser(userData))
      .catch(() => cookies().delete('auth_token')); // token无效则清除Cookie
    }
  }, []);
  
  const logout = () => {
    cookies().delete('auth_token');
    setUser(null);
  };
  
  return (
    <AuthContext.Provider value={{ user, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

export const useAuth = () => useContext(AuthContext);

关键注意事项

  • Middleware无法访问React的Context、状态等客户端专属API,必须依赖服务端可读取的标识(Cookie、请求头等)。
  • 使用HttpOnly Cookie存储token可避免XSS攻击,提升安全性。
  • 登录、登出时需同步更新Cookie和AuthContext状态,防止状态不一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 13:04:54