Next.js Middleware路由异常:isAuth与isAdmin函数失效求助
问题根源
Next.js Middleware 运行在服务器端(Edge Runtime),而 sessionStorage 是浏览器专属的存储 API,服务器环境中根本不存在这个对象——这就是 isAuth 和 isAdmin 函数完全失效的核心原因,它们永远拿不到 authToken,返回结果始终为 false。
解决方案
要让服务器端的 Middleware 能获取到用户认证信息,必须把 Token 存在HTTP Cookie中(Cookie 会在每次请求时自动携带到服务器),同时修改校验函数从请求的 Cookie 中读取 Token。
1. 修改 Middleware 代码
将请求对象传递给校验函数,让函数能读取请求中的 Cookie:
import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; import { isAuth } from "@/utils/isAuth"; import { isAdmin } from "@/utils/isAdmin"; export function middleware(request: NextRequest) { const auth = isAuth(request); if (!auth) { return NextResponse.redirect(new URL("/login", request.url)); } const admin = isAdmin(request); if (!admin) { return NextResponse.redirect(new URL("/posts", request.url)); } return NextResponse.next(); } export const config = { matcher: "/dashboard", };
2. 重写 isAuth 函数
从请求的 Cookie 中读取 Token:
import { NextRequest } from "next/server"; export function isAuth(request: NextRequest) { // 从请求Cookie中获取authToken const authToken = request.cookies.get("authToken")?.value; // 存在Token则返回true,否则false return !!authToken; }
3. 重写 isAdmin 函数
同样从 Cookie 取 Token,并且建议用 jwt.verify 代替 decode(同时验证 Token 签名的有效性,防止篡改):
import jwt from "jsonwebtoken"; import { NextRequest } from "next/server"; export function isAdmin(request: NextRequest) { const authToken = request.cookies.get("authToken")?.value; if (!authToken) return false; try { // 验证Token并解码,需传入你的JWT密钥 const decodedToken = jwt.verify(authToken, process.env.JWT_SECRET!) as { role?: string }; return decodedToken.role === "admin" || decodedToken.role === "developer"; } catch (error) { // Token验证失败或解码出错,返回false return false; } }
4. 登录时设置 Cookie(关键步骤)
登录成功后,要把生成的 JWT Token 存入 Cookie,而不是 sessionStorage。示例登录 API 路由代码:
// app/api/login/route.ts import { NextResponse } from "next/server"; import jwt from "jsonwebtoken"; export async function POST(request: Request) { // 这里替换成你的用户校验逻辑(比如验证账号密码) const user = { id: 123, role: "admin" }; // 生成JWT Token const token = jwt.sign(user, process.env.JWT_SECRET!, { expiresIn: "1d" }); // 创建响应并设置Cookie const response = NextResponse.json({ success: true }); response.cookies.set("authToken", token, { httpOnly: true, // 禁止前端JS读取,防范XSS攻击 secure: process.env.NODE_ENV === "production", // 生产环境强制HTTPS传输 sameSite: "strict", // 防范CSRF攻击 maxAge: 86400, // Cookie有效期1天(秒) path: "/", // 全站所有路由都能访问该Cookie }); return response; }
内容的提问来源于stack exchange,提问作者Habib
相关产品推荐
相关产品推荐

