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

Next.js App Router中如何在中间件访问sessionStorage实现鉴权

解决Next.js App Router中间件无法访问sessionStorage的路由保护问题

你猜的没错,sessionStorage是浏览器端的存储API,而Next.js的中间件运行在服务端/边缘环境,根本拿不到客户端的存储数据。要实现服务端层面的路由保护,必须把认证状态存在服务端可读取的位置,下面给两种实用方案:


方案一:自定义HttpOnly Cookie实现(轻量自主可控)

1. 登录时在服务端设置安全Cookie

放弃把用户数据存在sessionStorage,转而在登录校验通过后,用服务端逻辑设置HttpOnly类型的Cookie(这类Cookie客户端JS无法读取,更安全):

// app/api/login/route.js
import { cookies } from 'next/headers';

export async function POST(request) {
  const { email, password } = await request.json();
  // 这里替换成你的用户校验逻辑(比如查数据库)
  const user = await verifyUserCredentials(email, password);

  if (user) {
    // 设置带用户标识的Cookie
    cookies().set({
      name: 'auth_session',
      value: JSON.stringify({ userId: user.id, email: user.email }),
      httpOnly: true, // 禁止客户端JS读取,防XSS
      secure: process.env.NODE_ENV === 'production', // 生产环境强制HTTPS
      sameSite: 'strict',
      maxAge: 60 * 60 * 24, // 有效期1天
      path: '/',
    });
    return Response.json({ success: true });
  }

  return Response.json({ success: false }, { status: 401 });
}

2. 中间件读取Cookie做路由校验

在middleware.js里读取Cookie,判断用户是否有权限访问保护路由:

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

export function middleware(request: NextRequest) {
  // 读取认证Cookie
  const authSession = request.cookies.get('auth_session')?.value;
  // 定义需要保护的路由列表
  const protectedRoutes = ['/dashboard'];
  const isAccessingProtectedRoute = protectedRoutes.some(route => 
    request.nextUrl.pathname.startsWith(route)
  );

  // 未登录访问保护路由 → 重定向到登录页
  if (isAccessingProtectedRoute && !authSession) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  // 已登录访问登录页 → 重定向到仪表盘
  if (request.nextUrl.pathname === '/login' && authSession) {
    return NextResponse.redirect(new URL('/dashboard', request.url));
  }

  return NextResponse.next();
}

// 指定中间件生效的路由范围
export const config = {
  matcher: ['/login', '/dashboard/:path*'],
};

3. 客户端获取用户信息

在服务端组件里读取Cookie,把用户数据传给页面:

// app/dashboard/page.js
import { cookies } from 'next/headers';

export default async function DashboardPage() {
  const authSession = cookies().get('auth_session')?.value;
  const user = authSession ? JSON.parse(authSession) : null;

  return (
    <div>
      <h1>欢迎回来,{user?.email}</h1>
      {/* 仪表盘内容 */}
    </div>
  );
}

4. 登出逻辑

用Server Action清除Cookie:

// app/actions/authActions.js
'use server';

import { cookies } from 'next/headers';

export async function logout() {
  cookies().delete('auth_session');
}

方案二:用NextAuth.js(官方封装,省心省力)

如果不想自己写Cookie逻辑,直接用NextAuth.js,它封装了完整的认证流程,支持多种登录方式:

1. 安装依赖

npm install next-auth

2. 创建Auth配置文件

// app/api/auth/[...nextauth]/route.js
import NextAuth from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';

const handler = NextAuth({
  providers: [
    CredentialsProvider({
      name: '账号密码登录',
      credentials: {
        email: { label: '邮箱', type: 'email' },
        password: { label: '密码', type: 'password' },
      },
      async authorize(credentials) {
        // 替换成你的用户校验逻辑
        const user = await verifyUserCredentials(credentials.email, credentials.password);
        return user ? user : null;
      },
    }),
  ],
  session: { strategy: 'jwt' },
  pages: { signIn: '/login' }, // 指定自定义登录页路径
});

export { handler as GET, handler as POST };

3. 中间件里用NextAuth做校验

// middleware.js
import { getServerSession } from 'next-auth/next';
import { NextResponse } from 'next/server';
import { authOptions } from './app/api/auth/[...nextauth]/route';

export async function middleware(request) {
  const session = await getServerSession(authOptions);
  const protectedRoutes = ['/dashboard'];
  const isAccessingProtectedRoute = protectedRoutes.some(route => 
    request.nextUrl.pathname.startsWith(route)
  );

  if (isAccessingProtectedRoute && !session) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  if (request.nextUrl.pathname === '/login' && session) {
    return NextResponse.redirect(new URL('/dashboard', request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ['/login', '/dashboard/:path*'],
};

4. 客户端获取用户信息

用useSession钩子(仅限客户端组件):

// app/dashboard/page.js
'use client';

import { useSession } from 'next-auth/react';

export default function DashboardPage() {
  const { data: session } = useSession();

  if (!session) return <div>请先登录</div>;

  return (
    <div>
      <h1>欢迎回来,{session.user.email}</h1>
    </div>
  );
}

核心总结

服务端中间件无法读取客户端存储,必须将认证状态放在服务端可访问的介质(比如Cookie)里,才能实现可靠的路由拦截。如果追求快速开发,优先选NextAuth.js;如果需要高度自定义,就用HttpOnly Cookie方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 08:25:20