最近开始研究 Strapi,这是一个无头 CMS。由于它仅提供后端,前端部分包括身份验证流程需要你自己构建。显然,你不会想自己构建这些,而是使用市场上的某个身份验证库。
我早已计划使用 NextAuth
,所以这是一个完美的机会来实现它。因此,我们的设置是 Next + Strapi + NextAuth。
作为 NextAuth 的新手,首先需要一些基础教程和入门指南。但在深入研究 NextAuth 时,我发现这些教程并不完善:它们不是生产就绪的、已经过时或不完整……此外,NextAuth 的文档也不太清晰。虽然提到了一些功能,但并未详细说明如何使用它们,这是文档常见的问题(在我看来)。
目标
因此,我决定深入研究并通过编写代码来搞清楚一切。
使用最新的 Next,包括服务器组件和服务器操作。 使用 GoogleProvider 和 CredentialsProvider(邮箱 + 密码)的 NextAuth。 与 Strapi 的完全集成。
在查找了大量信息后,我发现并没有一个全面解释这个主题的资源。因此,我决定将其整理成系列文章并分享出来。这就是你现在看到的内容:唯一一个完整的 NextAuth 使用指南,涵盖了凭据提供商的使用,包括邮箱确认流程、忘记密码或更改密码以及错误处理。
即使你对 Strapi 部分不感兴趣,这个系列也能帮助你学习 NextAuth。我建议你完整阅读整个系列,因为我在某些章节中解释的内容在其他章节中会用到。更好的是,尝试跟着代码一起动手,以最大化你的学习效果。
结构在设置章节和一些理论知识之后,我们首先设置 GoogleProvider。这是对 NextAuth 的一个简单介绍。我们不需要表单和状态,直接进入 NextAuth 的功能和自定义。一旦完成了 GoogleProvider 的身份验证过程,我们将添加 CredentialsProvider 及其所有步骤,比如登录和登出、重置密码等。
我知道这超出了预期,内容超过了20部分,我对此感到抱歉。但我保证你会对如何在 Next 中使用 Strapi 和 NextAuth 构建一个完整的身份验证流程有一个扎实的理解。所以,不要被长度吓到。
我将每一章的代码上传到了 GitHub 的分支上,你可以在那里跟着一起操作。
希望你喜欢这个系列。
2/ Next + NextAuth + Strapi:项目设置
在开始之前,我们需要进行一些安装和配置。设置代码的最终版本可以在 GitHub(setup 分支)上查看。
1. Next
首先在名为 frontend
的文件夹中安装 Next。运行以下命令:
npx create-next-app@latest
在设置选项中,选择 TypeScript、src
文件夹、app router
和 Tailwind。
安装完成后,我们清理大部分模板代码,以便从一个空项目开始。
2. Strapi
快速安装 Strapi
。如果你想了解更多,可以查看 Strapi 快速入门指南。在名为 backend
的文件夹中安装 Strapi:
npx create-strapi-app@latest backend --quickstart --ts
--quickstart
标志表示 Strapi 会为你设置一个 SQLite 数据库。这完全是不可见的,你在开发模式中完全不需要担心这个数据库。--ts
添加了 TypeScript 支持。
我将项目命名为 backend
并选择了快速安装(Quickstart)类型。
安装完成后,Strapi 会自动启动,打开 http://localhost:1337/admin 并要求创建一个账户。这是主要的 Strapi 管理员账户,所以不要忘记这些凭据。所有数据都是本地存储的,所以你不必担心安全性。
到此为止,我们暂时完成了 Strapi 的设置。现在我们在 frontend
文件夹中有了 Next,在 backend
文件夹中有了 Strapi。
3. 使用 nodemailer 和 Brevo 在 Strapi 中设置邮件提供商
Strapi 的默认邮件插件基于 Sendmail。这可能在开发环境中有效,但在生产环境中不太可靠(如 Strapi 文档所述)。
因此,我们将使用不同的插件:provider-email-nodemailer
,并与外部提供商 Brevo(以前称为 SendinBlue)结合使用。注意,Strapi 有一个特定的 Brevo 插件,但使用 Nodemailer 设置更简单,因为我们使用的是 SMTP。
首先使用 Brevo 创建一个免费账户(无需信用卡)。它每天允许发送 300 封免费邮件,这对于开发目的来说已经足够了。创建一个 SMTP 密钥。然后将 SMTP 服务器、端口、登录名和密码放入 backend
文件夹中的 .env
文件:
# /backend/.env
SMTP_HOST=smtp-relay.brevo.com
SMTP_PORT=587
SMTP_USER=EDITME->someusername
SMTP_PASS=EDITME->somepassword
SMTP_DEFAULT_FROM=EDITME->someEmail
SMTP_DEFAULT_REPLYTO=EDITME->someEmail
邮件插件允许你从 Strapi 内部发送邮件,例如从控制器或服务内部发送。为了确保这些邮件中始终存在 from
和 replyto
值,我们在配置中设置了默认值(见下文),并在此处将它们声明为 SMTP_DEFAULT_FROM
和 SMTP_DEFAULT_REPLYTO
。
接下来,我们将安装 Strapi 插件 provider-email-nodemailer
。在 backend
(Strapi)文件夹中运行:
npm i @strapi/provider-email-nodemailer
遗憾的是,这里存在一些漏洞:
17 vulnerabilities (3 moderate, 14 high)
但截至 2024 年 5 月 3 日,该插件在6天前更新过,所以应该没问题。
接下来,我们需要激活并配置这个插件。添加以下设置:
// backend/config/plugins.js
module.exports = ({ env }) => ({
email: {
config: {
provider: 'nodemailer',
providerOptions: {
host: env('SMTP_HOST'),
port: env('SMTP_PORT'),
auth: {
user: env('SMTP_USER'),
pass: env('SMTP_PASS'),
},
// ... any custom nodemailer options
},
settings: {
defaultFrom: env('SMTP_DEFAULT_FROM'),
defaultReplyTo: env('SMTP_DEFAULT_REPLYTO'),
},
},
},
});
测试一切是否正常工作。启动 Strapi 并进入管理面板:http://localhost:1337/admin
。导航到:settings > email plugin > configuration
。找到“测试邮件发送”框,输入一个邮箱地址(你的)并点击发送。如果你正确地执行了上述步骤,这将发送一封电子邮件。
一些故障排除提示:
确保你在 backend
添加了环境变量!确保你在 .env
和config/plugins.js
中拼写正确。阅读后端终端中的错误信息。
大部分信息来源于这篇文章:如何轻松在 Strapi 中通过任意提供商发送电子邮件。
最后一点:Brevo 提供了一个漂亮的仪表板,包含发送统计和日志,你可以在其中查看已发送的邮件。
4. Google OAuth
当你构建一个允许用户使用 Google 帐户登录的项目时,你需要在 Google Cloud 平台上创建一个 OAuth2.0 客户端。此客户端将为你提供一个 client ID
和一个 client secret
,你稍后在配置 NextAuth 时会用到它们。
这个 YouTube 视频 会引导你完成整个过程。相关部分是从 3:28 到 6:00。顺便提一下,这是一位 YouTube 频道 Sakura Dev 的视频,该频道有很多关于 NextAuth 的信息,所以你可能想将其收藏。
步骤:
前往 https://console.cloud.google.com/ 为 Web 应用程序创建凭据 OAuth 客户端 ID。 填写名称(例如 test project
)、来源(http://localhost:3000)和回调 URL(http://localhost:3000/api/auth/callback/google)。获取 client ID
和secret
,并将它们放入frontend
文件夹根目录下的.env.local
文件中:
# .env.local
GOOGLE_CLIENT_ID=MYGOOGLECLIENTID
GOOGLE_CLIENT_SECRET=MYGOOGLECLIENTSECRET
注意,这些是机密信息。不要将它们推送到 git 仓库!如果你不知道回调 URL 是什么,不必担心,这只是一个设置步骤。它将你的前端 Next 与 Google 提供商链接起来。
5. 项目结构我们现在有两个文件夹:
frontend
用于 Nextbackend
用于 Strapi
我在每个文件夹中添加了
一个工作区文件。这让你可以轻松地为每个文件夹打开两个 VS Code 实例。我还为每个文件夹添加了不同的背景颜色,以便轻松区分前端和后端,并隐藏了 node_modules
文件夹。
6. 一些组件和样式在开始之前,我们添加一些组件并设置一些基本样式。我们将保持样式尽可能简单,因为这不是一篇关于用户体验的文章。
在我们的 root layout.tsx
中,我们添加了一个 <NavBar />
组件,目前只包含一个指向主页的链接。
export default async function NavBar() {
return (
<nav className='flex gap-4 items-center my-4 p-4 bg-zinc-100 rounded-sm'>
<Link href='/' className='mr-auto'>
home
</Link>
</nav>
);
}
接下来的步骤至此,我们结束了设置。在下一章中,我们将开始使用 NextAuth。