如何在NextJS页面路由中获取登录用户的ID?
解决方案
要直接在auth()返回的用户对象中获取id字段,你需要通过NextAuth的session回调自定义返回的session内容,同时扩展TypeScript类型以支持自定义字段:
1. 修改auth.ts添加Session回调
在你的auth.ts配置中,添加callbacks.session函数,将数据库用户的id注入到session对象里:
import NextAuth from 'next-auth'; import Credentials from 'next-auth/providers/credentials'; import { authConfig } from './auth.config'; import { z } from 'zod'; import { sql } from '@vercel/postgres'; import type { User } from '@/app/lib/definitions'; import bcrypt from 'bcrypt'; async function getUser(email: string): Promise<User | undefined> { try { const user = await sql<User>`SELECT * FROM users WHERE email=${email}`; return user.rows[0]; } catch (error) { console.error('Failed to fetch user:', error); throw new Error('Failed to fetch user.'); } } export const { auth, signIn, signOut } = NextAuth({ ...authConfig, callbacks: { // 保留原有的authorized回调 authorized({ auth, request: { nextUrl } }) { const isLoggedIn = !!auth?.user; const isOnDashboard = nextUrl.pathname.startsWith('/dashboard'); if (isOnDashboard) { if (isLoggedIn) return true; return false; } else if (isLoggedIn) { return Response.redirect(new URL('/dashboard', nextUrl)); } return true; }, // 添加session回调,注入用户id async session({ session, user }) { if (session.user && user.id) { session.user.id = user.id; } return session; }, }, providers: [ Credentials({ async authorize(credentials) { const parsedCredentials = z .object({ email: z.string().email(), password: z.string().min(6) }) .safeParse(credentials); if (parsedCredentials.success) { const { email, password } = parsedCredentials.data; const user = await getUser(email); if (!user) return null; const passwordsMatch = await bcrypt.compare(password, user.password); if (passwordsMatch){ return user; } } console.log('Invalid credentials'); return null; }, }), ], });
2. 扩展NextAuth TypeScript类型
由于NextAuth默认的User和Session类型不包含id字段,需要创建类型扩展文件(比如types/next-auth.d.ts)让TypeScript识别自定义字段:
import NextAuth from "next-auth"; import type { User as AppUser } from "@/app/lib/definitions"; declare module "next-auth" { // 复用你定义的User类型 interface User extends AppUser {} interface Session { user: User; } }
3. 验证效果
修改完成后,重新启动项目,在dashboard/page.tsx中调用auth()就能直接获取包含id的用户对象:
const user = await auth(); console.log(user); // 输出示例: // { // user: { id: "1", name: 'User toto', email: 'user@nextmail.com' }, // expires: '2025-01-12T13:47:17.724Z' // }
原理说明
NextAuth默认只会将name、email、image字段存入session,通过session回调可以将authorize函数返回的完整用户对象中的id(或其他自定义字段)注入到session中,这样后续通过auth()获取session时就能直接拿到这些字段,无需额外查询数据库。
内容的提问来源于stack exchange,提问作者Haifisch
相关产品推荐
相关产品推荐

