Next-Auth社交登录userId类型不匹配(String转Int)问题解决
解决Next-Auth社交登录后userId类型不匹配问题
问题本质:社交登录提供者(如Facebook)返回的用户ID是字符串类型,而你的PostgreSQL数据库中userId字段定义为Int,Prisma进行类型检查时就会抛出类型不匹配的错误。
下面是几种可行的解决办法:
方案一:在Next-Auth回调中统一转换ID类型
修改你的Next-Auth配置文件(通常是pages/api/auth/[...nextauth].js或App Router下的app/api/auth/[...nextauth]/route.js),通过jwt和session回调将用户ID转换为数字类型:
import NextAuth from "next-auth"; import FacebookProvider from "next-auth/providers/facebook"; // 导入其他需要的提供者 export const authOptions = { providers: [ FacebookProvider({ clientId: process.env.FACEBOOK_CLIENT_ID, clientSecret: process.env.FACEBOOK_CLIENT_SECRET, }), // 配置其他社交提供者 ], callbacks: { async jwt({ token, user }) { // 用户首次登录时,将user.id转为数字 if (user) { token.id = Number(user.id); } return token; }, async session({ session, token }) { // 将转换后的ID同步到session的user对象中 session.user.id = token.id; return session; }, }, }; export default NextAuth(authOptions);
配置完成后,从session中获取的user.id将是数字类型,后续传递给Prisma的查询就不会触发类型错误。
方案二:在Prisma查询时手动转换ID类型
如果不想修改Next-Auth的全局配置,可以在每次执行数据库查询前,将字符串类型的userId转换为数字:
import { getServerSession } from "next-auth/next"; import { prisma } from "@/lib/prisma"; import { authOptions } from "../auth/[...nextauth]"; export default async function handler(req, res) { const session = await getServerSession(req, res, authOptions); if (!session) { return res.status(401).json({ error: "未授权" }); } // 将字符串ID转为数字,同时校验有效性 const userId = parseInt(session.user.id, 10); if (isNaN(userId)) { return res.status(400).json({ error: "无效的用户ID" }); } const todos = await prisma.todos.findMany({ where: { userId }, select: { id: true, text: true, done: true }, }); res.status(200).json(todos); }
这种方式适合临时修复,但需要在所有涉及userId的查询中重复处理,维护成本较高。
方案三:调整数据库字段类型(备选)
如果项目处于早期阶段,没有大量历史数据,可以直接修改Prisma Schema,将userId字段类型从Int改为String:
model Todo { id Int @id @default(autoincrement()) text String done Boolean @default(false) userId String // 替换原有的Int类型 user User @relation(fields: [userId], references: [id]) } model User { id String @id @default(cuid()) // 推荐用String作为用户表ID,适配社交登录的字符串ID name String? email String? @unique emailVerified DateTime? image String? todos Todo[] accounts Account[] sessions Session[] }
修改后运行npx prisma migrate dev更新数据库结构。如果已有历史数据,需要额外处理数据迁移,将原有的Int类型userId转换为String。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

