Next.js中构建完整的身份验证系统【翻译】

案例使用第三方库:NextAuth.js, Shadcn/ui, react-hook-form, and Zod等

  • prisma: is an open-source database toolkit. We will use it to store user credentials.
  • next-auth: Authentication for Next.js.
  • react-hook-form: a library that helps you validate forms in React.
  • zod: a data validator.
  • bcrypt: to hash passwords.
  • shadcn/ui: a collection of reusable components.

简要概述:

确保用户的安全和隐私比以往任何时候都更加重要。 Web认证在这方面发挥着至关重要的作用,是保护用户信息和数据的第一道防线。
今天,我们拥有像 NextAuth.js 这样的工具,使我们的工作变得更加轻松,使我们能够在 Next.js 应用程序中轻松实现不同类型的身份验证。
在本系列教程中,我们将在 Next.js 14 中构建一个完整的身份验证系统,从基础知识开始:使用电子邮件和密码进行身份验证。

什么是 NextAuth.js (Auth.js)?

在 JavaScript 生态系统中,更具体地说,在使用 Next.js 开发的应用程序中,处理身份验证的最著名的库之一是 NextAuth.js。
该工具提供了一个简单且易于实施的解决方案,用于向我们的应用程序添加身份验证。最好的一点是它的灵活性;除了基于凭证的身份验证(例如经典的电子邮件和密码)之外,它还允许集成不同的身份验证提供商(例如 Google、Facebook 和 Twitter)。

实现凭证认证 Authentication

凭证验证是非常有用的在需要完全控制验证过程和用户凭证存储的应用程序中,或者当您不想依赖外部身份验证提供商时。

起步

  1. 使用以下命令创建一个新的Next.js项目,并按照指示的步骤进行操作。我们将使用TypeScript和src/文件夹。
npx create-next-app@latest
  1. 安装项目需要的依赖,使用pnpm进行依赖管理
pnpm install next-auth prisma react-hook-form zod, bcrypt

我们使用Shadcn/ui组件

pnpm dlx shadcn-ui@latest init
  • prisma: 是一个开源数据库工具包。我们将使用它来存储用户凭据。
  • next-auth: Next.js的身份验证。
  • react-hook-form: 一个帮助你在React中验证表单的库。
  • zod: 数据验证器。
  • bcrypt: 对密码进行哈希运算。
  • shadcn/ui: 可重用UI组件的集合。
  1. 为项目创建以下结构
...
├── prisma/
...
├── src/
│   ├── actions/
│   │   └── auth-actions.tsx
│   ├── app/
│   │   ├── api/auth/[...nextauth]
│   │   │   └── route.ts
│   │   ├── auth/
│   │   │   ├── signin
│   │   │   │   └── page.tsx
│   │   │   └── signup
│   │   │       └── page.tsx
│   │   │   ...   
│   ├── components/
│   │   ├── auth/
│   │   │   ├── auth-buttons.tsx
│   │   │   ├── signin-form.tsx
│   │   │   ├── signup-form.tsx
│   │   │   └── user-nav.ts
│   │   ├── ui/
│   │   │   ...
│   │   ├── auth-provider.tsx
│   │   ├── icons.tsx
│   │   └── theme-provider.tsx
│   ├── lib/
│   │   ├── prisma.ts
│   │   ├── types.d.ts
│   │   └── utils.ts
│   ...
...

设置Prisma,初始化数据结构

我们将使用Prisma在数据库中存储和检索用户。Prisma允许集成不同的数据库类型,因此您可以使用所需的任何数据库,我们将使用SQLite

初始化Prisma

npx prisma init --datasource-provider sqlite 

这将创建包含其数据model的数据文件夹。

创建 models.

为了创建模型,我们将使用@auth/prisma-adapter提供的模型,并对其进行一些自定义,如下所示

generator client {
   
   
  provider = "prisma-client-js"
  output = "../../node_modules/.prisma/client"
}

datasource db {
   
   
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

...
model User {
   
   
  id            String    @id @default(cuid())
  username      String
  password      String
  email         String    @unique
  emailVerified DateTime?
  phone         String?
  image         String?
}

创建第一个migration

npx prisma migrate dev --name first-migration

使用此命令,在Prisma文件夹中创建了更多文件,数据库已与模型同步。

Prisma客户端

最后,我们创建一个Prisma客户端代码。

import {
   
    PrismaClient } from "@prisma/client";

const globalForPrisma = global as unknown as {
   
   
  prisma: PrismaClient;
};

export const prisma = globalForPrisma.prisma || new PrismaClient();

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

export default prisma;

设置NextAuth.js

创建 .env 环境变量

# Secret key for NextAuth.js, used for encryption and session security.  It should be a long,
# random string unique to your application.
NEXTAUTH_SECRET=XXX3B2CC28F123456C6934531CXXXXX

# Base URL for your Next.js app, used by NextAuth.js for redirects and callbacks.
NEXTAUTH_URL=http://localhost:3000/

创建身份auth验证路由

此路径允许在单个端点上处理所有身份验证请求(如登录、注销和供应商回调)。
src/app/api/auth/[...nextauth]

创建providers

...
// Imports the Prisma User type for typing.
import {
   
    User } from '@prisma/client'

// Configuration of authentication options for NextAuth.
export const authOptions: AuthOptions = {
   
   
  ...
 // Defines authentication providers, in this case, only credentials.
 providers: [
  CredentialsProvider({
   
   
   name: 'Credentials',
   // Defines the required fields for authentication.
   credentials: {
   
   
    email: {
   
    label: 'Email', type: 'text' },
    password: {
   
    label: 'Password', type: 'password' },
   },
   // Function to authenticate the user with the provided credentials.
   async authorize(credentials) {
   
   
    // Searches for the user in the database by email.
    const user = await prisma.user.findUnique({
   
   
     where: {
   
   
      email: credentials?.email,
     },
    })

    // Checks if the user exists and if the password is correct.
    if (!user) throw new Error('User name or password is not correct')

    if (!credentials?.password) throw new Error('Please Provide Your Password')
    const isPasswordCorrect = await bcrypt.compare(credentials.password, user.password)

    if (!isPasswordCorrect) throw new Error('User name or password is not correct')

    // Returns the user without including the password.
    const {
   
    password, ...userWithoutPass } = user
    return userWithoutPass
   },
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值