当前位置: 首页 > article >正文

next-auth v5 结合 Prisma 实现登录与会话管理

1. 安装依赖

npm install next-auth prisma @prisma/client

2. 配置 Prisma 模型

在 prisma/schema.prisma 文件中定义 User 和 Account 模型(next-auth v5 推荐使用自定义模型)。

model User {
  id            String    @id @default(uuid())
  email         String    @unique
  name          String?
  image         String?
  hashedPassword String?
  accounts      Account[]
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt
}

model Account {
  id               String  @id @default(uuid())
  userId           String
  provider         String
  providerAccountId String
  user             User    @relation(fields: [userId], references: [id], onDelete: Cascade)
  createdAt        DateTime @default(now())
  updatedAt        DateTime @updatedAt
}

运行 prisma migrate 同步数据库:

npx prisma migrate dev --name init

3. 创建 next-auth 配置

pages/api/auth/[...nextauth].ts 文件中添加 next-auth 配置:

import NextAuth, { AuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { PrismaClient } from "@prisma/client";
import { compare } from "bcryptjs"; // 假设密码是加密存储的

const prisma = new PrismaClient();

export const authOptions: AuthOptions = {
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        if (!credentials?.email || !credentials.password) {
          throw new Error("Missing email or password");
        }

        // 查找用户
        const user = await prisma.user.findUnique({
          where: { email: credentials.email },
        });

        if (!user) {
          throw new Error("No user found");
        }

        // 验证密码
        const isValidPassword = await compare(
          credentials.password,
          user.hashedPassword
        );

        if (!isValidPassword) {
          throw new Error("Invalid credentials");
        }

        return { id: user.id, email: user.email, name: user.name };
      },
    }),
  ],
  session: {
    strategy: "jwt",
  },
  callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token.id = user.id;
      }
      return token;
    },
    async session({ session, token }) {
      if (token) {
        session.user.id = token.id;
      }
      return session;
    },
  },
};

export default NextAuth(authOptions);`

4. 创建登录页面

示例的登录页面:

import { signIn } from "next-auth/react";
import { useState } from "react";

export default function LoginPage() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError] = useState("");

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const result = await signIn("credentials", {
      email,
      password,
      redirect: false,
    });

    if (result?.error) {
      setError(result.error);
    } else {
      // 登录成功,跳转
      window.location.href = "/";
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Email</label>
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          required
        />
      </div>
      <div>
        <label>Password</label>
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          required
        />
      </div>
      {error && <p style={{ color: "red" }}>{error}</p>}
      <button type="submit">Login</button>
    </form>
  );
}

5. 使用会话信息

在需要使用用户会话的页面中:

import { useSession, signOut } from "next-auth/react";

export default function Dashboard() {
  const { data: session, status } = useSession();

  if (status === "loading") {
    return <p>Loading...</p>;
  }

  if (!session) {
    return <p>You are not logged in</p>;
  }

  return (
    <div>
      <h1>Welcome, {session.user.name}</h1>
      <button onClick={() => signOut()}>Sign out</button>
    </div>
  );
}

6. 运行应用

npm run dev

关键点说明

密码存储:建议在用户注册时使用 bcrypt 对密码进行加密存储。
Session 策略:此示例使用 JWT 策略,如果需要使用数据库会话,可以将 session.strategy 设置为 “database” 并配置 Prisma 的 Session 模型。
错误处理:authorize 方法中抛出的错误会显示在客户端,可以根据需求自定义错误提示。


http://www.kler.cn/a/505123.html

相关文章:

  • C#常用257单词
  • C语言,无法正常释放char*的空间
  • [BSidesCF 2020]Had a bad day1
  • 网络工程师 (3)指令系统基础
  • 蓝桥杯模拟算法:蛇形方阵
  • CAN总线
  • NVIDIA PyTorch Docker 镜像安装
  • RustDesk ID更新脚本
  • macos 一直报错 XXX 将对你的电脑造成伤害。你应该将它移到废纸篓
  • VSCode开发STM32,并支持C++
  • Spring官网构建Springboot工程
  • 【llama_factory】qwen2_vl训练与批量推理
  • DAMA GDPA 备考笔记(二)
  • 3.flask蓝图使用
  • 【优选算法篇】--双指针篇
  • C# PDF下载地址转图片(Base64 编码)
  • Ubuntu/centOS 如何安装 OpenGL
  • Web前端------HTML多媒体标签之图片标签
  • 开始使用Panuon开源界面库环境配置并手写VS2019高仿界面
  • 网安——计算机网络基础
  • 【HTML+CSS+JS+VUE】web前端教程-35-字体图标
  • 【AI】【RAG】如何通过WebUI部署与优化RAG问答系统
  • 深度探索:Go 语言日志增强工具 Devslog 的全面解析
  • 配置Kubernetes从节点与集群Calico网络
  • Java算法 数据结构 栈 单调栈实战 模版题 [洛谷-P5788]
  • WOA-CNN-LSTM-Attention、CNN-LSTM-Attention、WOA-CNN-LSTM、CNN-LSTM四模型对比多变量时序预测