如何区分NextAuth中用户的登录与注册,实现新用户昵称设置?
区分NextAuth谷歌登录的首次注册与已有用户登录
要实现判断用户是首次注册还是已有用户登录,核心思路是通过数据库用户记录的状态标记来区分——因为NextAuth的signIn接口本身不区分登录/注册,首次登录即为自动注册。具体步骤如下:
1. 扩展用户表字段
在Prisma的schema文件中,给User模型新增一个标记字段,用于识别用户是否完成首次昵称设置:
model User { id String @id @default(cuid()) name String? email String @unique emailVerified DateTime? image String? createdAt DateTime @default(now()) // 新增字段:标记是否完成个人信息初始化(默认未完成) isProfileCompleted Boolean @default(false) sessions Session[] accounts Account[] }
执行npx prisma migrate dev同步数据库变更。
2. 配置NextAuth传递状态字段
在NextAuth的配置文件(pages/api/auth/[...nextauth].js)中,通过session回调将用户的isProfileCompleted字段加入前端可访问的session中:
import NextAuth from "next-auth"; import GoogleProvider from "next-auth/providers/google"; import { PrismaAdapter } from "@next-auth/prisma-adapter"; import prisma from "../../../lib/prisma"; export default NextAuth({ providers: [ GoogleProvider({ clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, }), ], adapter: PrismaAdapter(prisma), callbacks: { async session({ session, user }) { // 将用户状态字段注入session session.user.isProfileCompleted = user.isProfileCompleted; session.user.id = user.id; return session; }, }, // 可选:监听用户创建事件,做注册初始化操作 events: { async createUser({ user }) { console.log(`新用户注册:${user.email}`); // 可在这里添加欢迎通知、初始化用户默认数据等操作 }, }, });
3. 前端判断并引导昵称设置
在登录后的入口页面(比如仪表盘pages/dashboard.js),通过useSession获取用户状态,判断是否需要跳转到昵称设置页面:
import { useSession } from "next-auth/react"; import { useEffect } from "react"; import { useRouter } from "next/router"; export default function Dashboard() { const { data: session } = useSession(); const router = useRouter(); useEffect(() => { if (session && !session.user.isProfileCompleted) { // 未完成昵称设置,跳转至配置页面 router.push("/profile-setup"); } }, [session, router]); if (!session) { return <div>请先登录</div>; } return <div>欢迎回来,{session.user.name}</div>; }
4. 实现昵称设置页面
创建pages/profile-setup.js,用于用户设置昵称并更新数据库状态:
import { useSession } from "next-auth/react"; import { useState } from "react"; import { useRouter } from "next/router"; import prisma from "../../lib/prisma"; export default function ProfileSetup() { const { data: session } = useSession(); const [nickname, setNickname] = useState(""); const router = useRouter(); const handleSubmit = async (e) => { e.preventDefault(); if (!nickname.trim()) return; try { await prisma.user.update({ where: { id: session.user.id }, data: { name: nickname, // 若需单独存储昵称,可修改为对应字段名 isProfileCompleted: true, }, }); router.push("/dashboard"); } catch (error) { console.error("更新昵称失败:", error); } }; if (!session) { return <div>请先登录</div>; } return ( <form onSubmit={handleSubmit}> <h2>设置你的昵称</h2> <input type="text" value={nickname} onChange={(e) => setNickname(e.target.value)} placeholder="输入你的昵称" required /> <button type="submit">确认设置</button> </form> ); }
补充:直接在后端判断登录/注册
如果需要在后端逻辑中区分,可在NextAuth的signIn回调中查询数据库(注意:Prisma Adapter会在signIn回调后创建新用户,所以首次登录时查询会返回null):
callbacks: { async signIn({ user }) { const existingUser = await prisma.user.findUnique({ where: { email: user.email }, }); if (!existingUser) { // 首次登录(注册)逻辑 } else { // 已有用户登录逻辑 } return true; }, },
内容的提问来源于stack exchange,提问作者Intaek
相关产品推荐
相关产品推荐

