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

ops/2025/1/17 14:51:49/

1. 安装依赖

npm install next-auth prisma @prisma/client

2. 配置 Prisma 模型

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

javascript">model User {id            String    @id @default(uuid())email         String    @uniquename          String?image         String?hashedPassword String?accounts      Account[]createdAt     DateTime  @default(now())updatedAt     DateTime  @updatedAt
}model Account {id               String  @id @default(uuid())userId           Stringprovider         StringproviderAccountId Stringuser             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 配置:

javascript">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. 创建登录页面

示例的登录页面:

javascript">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><inputtype="email"value={email}onChange={(e) => setEmail(e.target.value)}required/></div><div><label>Password</label><inputtype="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. 使用会话信息

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

javascript">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.ppmy.cn/ops/150831.html

相关文章

css hover样式调试

调试 hover后才出现的元素如何调试 打开开发者工具&#xff0c;鼠标放在hover时才出现的元素上&#xff0c;然后点击右键不要选中任何选项&#xff0c;将鼠标移动到开发者工具的调试面板中按下N键&#xff0c;此时悬浮的元素不会消失&#xff0c;定位成功 调试元素悬浮样式 …

[答疑]用例规约:系统请求3dsMax创建体块

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 第五元素 2024-12-22 12:39 潘老师&#xff0c;请教一个问题&#xff1a;在需求工作流书写系统用例规约时&#xff0c;这个“计算”&#xff08;改变&#xff09;可不可以写多个内容&…

vue用户点进详情页再返回列表页,停留在原位置

在 Vue 中使用 <keep-alive> 来缓存组件确实可以提高用户体验&#xff0c;尤其是在移动应用中。然而&#xff0c;有时候你可能希望某些页面在每次访问时都重新加载&#xff0c;而不是使用缓存的版本。为了实现这一点&#xff0c;你可以结合 key 属性和 Vue Router 的导航…

【React学习笔记】第一章:React入门

1.React介绍 中文官网&#xff1a; https://react.docschina.org/ 英文官网&#xff1a;https://reactjs.org/ 1.1 React是什么 react是一个用于构建用户界面的开源JavaScript库。&#xff08;操作DOM呈现页面&#xff09; 由Facebook的软件工程师 Jordan Walke创建&#xf…

基于微信小程序的中国各地美食推荐平台的设计与实现springboot+论文源码调试讲解

第4章 系统设计 4.1 系统设计的原则 在系统设计过程中&#xff0c;也需要遵循相应的设计原则&#xff0c;这些设计原则可以帮助设计者在短时间内设计出符合设计规范的设计方案。设计原则主要有可靠性&#xff0c;安全性&#xff0c;可定制化&#xff0c;可扩展性&#xff0c;可…

【Kotlin】上手学习之类型篇

一、类型 1.1 基本类型 主要分为 数字及其无符号版布尔字符字符串数组 1.1.1 数字 整数类型 Kotlin 提供了一组表示数字的内置类型。 对于整数&#xff0c;有四种不同大小的类型&#xff0c;因此值的范围也不同&#xff1a; 类型大小&#xff08;比特数&#xff09;最小…

2006-2020年各省人均水资源量数据

2006-2020年各省人均水资源量数据 1、时间&#xff1a;2006-2020年 2、来源&#xff1a;国家统计局、统计年鉴 3、指标&#xff1a;行政区划代码、地区名称、年份、人均水资源量 4、范围&#xff1a;31省 5、指标解释&#xff1a;人均水资源量是指一个国家或地区在一定时期…

基于单片机的多功能门铃控制系统设计(论文+源码)

1功能设计 本课题为基于单片机的多功能门铃控制系统设计&#xff0c;主要结合单片机技术&#xff0c;门铃控制技术进行设计&#xff0c;在多功能门铃控制系统的设计中&#xff0c;将其主要的设计功能确定如下&#xff1a; &#xff08;1&#xff09;可以实现门铃的基础功能&am…