今天我们来了解一下使用 NextAuth 设置受保护的路由。
关于这方面的文章非常杂乱,着实让我头痛。
我将尽量根据官方文档编写。
1. 写这篇文章的原因

我已经用 NextAuth 实现了登录。
问题在于,当我想同时使用路由保护和重定向时。
我想让未登录和已登录的用户访问根路径 “/” 时都重定向到 “/category”。
并且希望阻止已登录用户访问 “/profile” 或 “/login” 路径。
然而,关于这一点的文章不多,而且 chatgpt 也总是胡说八道,让我很无奈。
2. NextAuth 官方文档

最后通过搜索和官方文档解决了。
果然 官方文档 很棒。
点击该链接可以看到如何结合使用 NextAuth 和 middleware。
import { withAuth } from "next-auth/middleware";
export default withAuth(
// `withAuth` 增强你的 `Request`,使其可以使用用户的 token。
function middleware(req) {
console.log(req.nextauth.token);
},
{
callbacks: {
authorized: ({ token }) => token?.role === "admin",
},
}
);
export const config = { matcher: ["/admin"] };
这里的关键是使用 withAuth 包装 middleware 可以访问请求者的 token。
如果不需要 token,可以在 middleware 内部处理,如果需要认证,则通过 callbacks 处理。
middleware 内部也可以处理,所以不一定非要通过 callback。
3. 实现功能

现在让我们来应用一下。
用 withAuth 包裹 middleware。
简单地说就是 withAuth(middleware, callbacks: {}) 的格式。
请求进来时先在 middleware 中处理,然后再传递下去。
先来看代码吧。
import { withAuth } from "next-auth/middleware";
import { NextResponse } from "next/server";
// 使用 withAuth 包裹的 middleware 导出
export default withAuth(
function middleware(req) {
// 访问根 URL(/)时重定向到 /category
if (req.nextUrl.pathname === "/") {
return NextResponse.redirect(new URL("/category", req.url));
}
if (
req.nextauth.token?.authLevel !== "admin" &&
req.nextUrl.pathname.startsWith("/dashboard")
) {
return NextResponse.redirect(new URL("/category", req.url));
}
return NextResponse.next();
},
{
callbacks: {
authorized: ({ token, req }) => {
// 检查 dashboard 权限
// 只有以 profile 开头的路径需要认证
if (req.nextUrl.pathname.startsWith("/profile")) {
return !!token;
}
// 其他路径始终返回 true
return true;
},
},
}
);
export const config = {
matcher: [
"/((?!api|_next/static|_next/image|.*\\.avif$).*)", // 排除静态文件
"/",
"/dashboard",
"/profile/:path*", // 仅包括 profile 路径
],
};
这样,所有用户访问 “/” 时将被重定向到 “/category”。
不是 “admin” 权限的已登录用户在访问 “/dashboard” 路径时将被重定向。
未登录用户访问 “/profile” 时会显示登录界面。
其他情况可以根据需要利用 token 实现。
4. 后记

紧跟当前的 Web 开发趋势对普通人来说并不容易,我又一次意识到了这一点。
由于 express 已经积累了大量数据,只需在 AI 中输入关键字即可生成代码,而 Nextjs 则不是这样。
在 Reddit 或者 Stack Overflow 上也有很多关于 AI 不能紧跟最新趋势的反馈。
这可能就是为什么开发人员仍然(?)需要的原因吧。
我需要提高英语水平,努力阅读官方文档。
댓글을 불러오는 중...