基于中间件的路由保护
使用 Next.js 中间件和身份验证回调,在边缘将未验证身份的用户重定向。
基于中间件的路由保护 是 CoddyKit 上的免费 React Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。
什么是 Next.js 中间件
中间件会在请求到达路由之前于边缘运行环境中执行。它可以重定向请求、重写请求或添加标头,非常适合在不加载服务器组件的情况下执行身份验证检查。
创建中间件
在项目根目录创建 middleware.ts。导出一个 middleware 函数和一个 config 匹配器。
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token')?.value;
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/dashboard/:path*', '/profile/:path*'],
};匹配器模式
matcher 数组使用路径模式。对于任意子路径,请使用 :path*;也可以使用负向前瞻排除路径。
export const config = {
matcher: [
// Protect all routes except public ones:
'/((?!login|register|_next|api/auth|favicon.ico).*)',
],
};Auth.js 中间件集成
Auth.js(v5)提供了开箱即用的中间件导出项。请在 middleware.ts 中结合匹配器重新导出它。
// middleware.ts
export { auth as middleware } from '@/auth';
export const config = {
matcher: ['/dashboard/:path*', '/settings/:path*'],
};在中间件中检查 JWT
请使用 jose 库在中间件中验证 JWT 令牌(兼容边缘运行环境 — 无需 Node.js 的加密模块)。
import { jwtVerify } from 'jose';
export async function middleware(request: NextRequest) {
const token = request.cookies.get('token')?.value;
if (!token) return NextResponse.redirect(new URL('/login', request.url));
try {
await jwtVerify(token, new TextEncoder().encode(process.env.JWT_SECRET));
return NextResponse.next();
} catch {
return NextResponse.redirect(new URL('/login', request.url));
}
}基于角色的中间件
从令牌中读取用户角色;如果角色权限不足,则将用户重定向到未授权页面。
const { payload } = await jwtVerify(token, secret);
if (request.nextUrl.pathname.startsWith('/admin') && payload.role !== 'admin') {
return NextResponse.redirect(new URL('/unauthorized', request.url));
}向路由处理程序传递数据
在中间件中设置请求标头,将解码后的用户数据传递给服务器组件,从而无需重新获取令牌。
const response = NextResponse.next();
response.headers.set('x-user-id', payload.sub as string);
response.headers.set('x-user-role', payload.role as string);
return response;
// In a Server Component:
import { headers } from 'next/headers';
const userId = headers().get('x-user-id');在中间件中重写 URL
使用 NextResponse.rewrite() 为某个 URL 提供不同的页面,同时不改变浏览器的地址栏 — 这对 A/B 测试或功能开关很有用。
const isInExperiment = Math.random() > 0.5;
if (isInExperiment) {
return NextResponse.rewrite(new URL('/home-v2', request.url));
}中间件中的地理位置和 IP
从 NextRequest 对象中获取请求的地理数据和 IP,以执行基于地区的重定向或拦截。
const country = request.geo?.country ?? 'US';
if (country === 'XX') {
return NextResponse.redirect(new URL('/region-blocked', request.url));
}中间件性能
中间件会在边缘运行环境中处理每个匹配的请求。请保持中间件轻量 — 避免执行繁重的计算或导入大型模块,并且只能使用兼容边缘运行环境的库。
组合身份验证路由和公开路由
一种常见模式是:除了特定的公开路径允许列表之外,保护所有路径,并在身份验证逻辑之前检查该列表。
const PUBLIC_PATHS = ['/login', '/register', '/about'];
const isPublic = PUBLIC_PATHS.some(p => request.nextUrl.pathname.startsWith(p));
if (isPublic) return NextResponse.next();
// Auth check for non-public routes
const token = request.cookies.get('token')?.value;
if (!token) return NextResponse.redirect(new URL('/login', request.url));快速检查
在 Next.js 中间件内验证 JWT 时,应使用哪个库,而不是 Node.js 的加密模块?
回顾
在项目根目录创建 middleware.ts,并配置 matcher。使用兼容边缘运行环境的 jose 检查身份验证令牌,重定向未通过身份验证的用户,并通过响应标头将解码后的数据传递给服务器组件。保持中间件快速且依赖精简。
常见问题解答
「基于中间件的路由保护」课时是免费的吗?
是的 — 「基于中间件的路由保护」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。
「基于中间件的路由保护」这节课中我会学到什么?
使用 Next.js 中间件和身份验证回调,在边缘将未验证身份的用户重定向。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「基于中间件的路由保护」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Academy 课中编写并运行代码吗?
能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。