使用 NextAuth 设置受保护的路由

힘센캥거루
2025년 1월 3일
3
107

今天我们来了解一下使用 NextAuth 设置受保护的路由。

关于这方面的文章非常杂乱,着实让我头痛。

我将尽量根据官方文档编写。

1. 写这篇文章的原因

使用 NextAuth 设置受保护的路由-1

我已经用 NextAuth 实现了登录。

问题在于,当我想同时使用路由保护和重定向时。

我想让未登录和已登录的用户访问根路径 “/” 时都重定向到 “/category”。

并且希望阻止已登录用户访问 “/profile” 或 “/login” 路径。

然而,关于这一点的文章不多,而且 chatgpt 也总是胡说八道,让我很无奈。

2. NextAuth 官方文档

使用 NextAuth 设置受保护的路由-2

最后通过搜索和官方文档解决了。

果然 官方文档 很棒。

点击该链接可以看到如何结合使用 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. 实现功能

使用 NextAuth 设置受保护的路由-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. 后记

使用 NextAuth 设置受保护的路由-4

紧跟当前的 Web 开发趋势对普通人来说并不容易,我又一次意识到了这一点。

由于 express 已经积累了大量数据,只需在 AI 中输入关键字即可生成代码,而 Nextjs 则不是这样。

在 Reddit 或者 Stack Overflow 上也有很多关于 AI 不能紧跟最新趋势的反馈。

这可能就是为什么开发人员仍然(?)需要的原因吧。

我需要提高英语水平,努力阅读官方文档。

관련 글

Next.js 全栈博客开发记
Next.js 全栈博客开发记
在第一次接触网页开发大约 1 年之后,我开始想着想要拥有一个属于自己的博客。于是我就大概花了 6 个月几乎只埋头做这件事。前端部分的功能,参考金度亨先生的博客就已经足够了。我用 mdx 搭建起一个博客,其实连一周都没花到。事实上,仅靠前端也并不会给博客运营带来什么大问题。有一阵子我也觉得,只要写 m...
使用 Caddy 实现 Next.js 无停机部署(本地服务器)
使用 Caddy 实现 Next.js 无停机部署(本地服务器)
每次一有想在主页上加点什么的念头就去 build,结果中间好像偶尔会有人访问。于是 Search Console 上的分数开始一点点往下掉。觉得这样不行,就开始思考要怎么做无停机部署。1. 两个项目文件夹 + 两个终端答案出乎意料地简单:开两个终端。在一个终端里 build,另一个终端里让服务器跑着...
谷歌搜索索引自动化 - Web Search Indexing API
谷歌搜索索引自动化 - Web Search Indexing API
继上次搞完 IndexNow 之后,也决定在谷歌这边做一下自动化。查了一下,发现谷歌是通过一个叫 Web Search Indexing 的 API 来支持这个功能的。1. 适用范围官方文档中,这个 API 正式支持的范围是招聘公告和流媒体视频服务。说是为了给对实时性要求高的内容创建索引用的,但搜了...
搜索索引生成自动化 - IndexNow
搜索索引生成自动化 - IndexNow
在向 Bing 提交站点收录时才发现,Bing 提供了一个叫做 IndexNow 的功能。核心在于,可以利用 API Key,在写完文章的瞬间就立刻发起索引请求。只要用 fetch 写出类似下面这样的请求,并把它串联到「写文章」流程里,就可以在把文章保存到 DB 的同时发送索引生成请求。POST /...
被入侵的 Nextjs、React 服务器经历
被入侵的 Nextjs、React 服务器经历
我最初接触到这次安全问题是在 12 月 5 日凌晨。据说在 React 中可以在未认证的情况下进行远程代码执行。看到这条新闻后,我虽然告诉了别人,但总觉得自己应该没事,就什么想法也没有地略过了。1. 发现被入侵的痕迹结果当我想登录更新博客代码时,在终端里发现了有命令被执行过的痕迹。/bin/sh:...
在博客中添加多语言功能(NextJS、next-intl、Vercel AI SDK)
在博客中添加多语言功能(NextJS、next-intl、Vercel AI SDK)
最近我觉得博客需要多语言功能。于是决定用 next-intl 来实现多语言服务。1.i18n首先,在做多语言服务时有一些必须遵守的原则。这被称为 internationalization,单词太长,所以把首字母 i 和尾字母 n,以及中间 18 个字母合在一起,写成 i18n。1) i18n 的原则...

댓글을 불러오는 중...