ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

create-t3-app 中的 NextAuth.js 集成指南:从会话管理到 tRPC 鉴权实战

create-t3-app 中的 NextAuth.js 集成指南:从会话管理到 tRPC 鉴权实战 开发工具CLI代码生成【免费下载链接】create-t3-appThe best way to start a full-stack, typesafe Next.js app项目地址https://gitcode.com/gh_mirrors/cr/create-t3-app点击查看免费下载本篇技术指南以 create-t3-app 官方文档葡萄牙语版 / 英语版为主体系统讲解在 T3 Stack 脚手架中如何使用 NextAuth.js 实现完整认证体系客户端与服务端会话获取、user.id类型安全注入、与 tRPC 的 protectedProcedure 鉴权集成、与 Prisma/Drizzle 的适配器配置以及 Discord OAuth Provider 的端到端接入。读完本文你将掌握 T3 应用从零到可登录、可鉴权、可读库的全链路实战能力并理解脚手架底层生成的真实源码结构。为什么在 T3 应用中选择 NextAuth.js当你需要为 Next.js 应用引入认证系统时NextAuth.js 是引入复杂安全性而又无需从零构建的绝佳方案。它内置了大量 OAuth Provider可以快速接入 GitHub、Discord、Google 等第三方登录并为众多数据库与 ORM 提供了官方适配器Adapter。在 create-t3-app 生成的脚手架中选择 NextAuth.js 后你会得到一套开箱即用的认证体系认证配置、会话辅助函数、类型声明、数据库模型Prisma Schema 或 Drizzle 表结构与环境变量占位符全部预置完毕你只需要提供 OAuth 令牌即可运行。需要说明的是本仓库的葡语文档对应的模板结构为 Pages Router 时代pages/api/auth/[...nextauth].ts、server/common/get-server-auth-session.ts而当前仓库模板已演进为 App Router Auth.js v5 的结构见 src/server/auth/index.ts。本文会以葡语文档为主线讲解核心概念同时结合当前仓库的真实模板源码给出最新写法两者对照更有助于理解演进脉络。Context Provider在客户端任意位置访问会话在你的应用入口处你会发现整个应用被 SessionProvider 包裹SessionProvider session{session} Component {...pageProps} / /SessionProvider这个上下文 Provider 让你的应用无需通过 props 层层传递即可在任意组件中访问会话数据import { useSession } from next-auth/react; const User () { const { data: session } useSession(); if (!session) { // 处理未认证状态例如渲染一个 SignIn 组件 return SignIn /; } return pBem-vindo {session.user.name}!/p; };useSession()返回的data在未登录时为null登录后包含user、expires等字段。注意不要把认证逻辑完全寄托于客户端——客户端会话只是便捷的 UI 展示手段真正的鉴权必须依赖服务端校验。在服务端获取会话有些场景你需要在服务端请求会话比如在getServerSideProps中做服务端渲染前的数据预取。Pages Router 写法对应葡语文档使用 create-t3-app 提供的getServerAuthSession辅助函数并通过getServerSideProps将预取的会话传递给客户端import { getServerAuthSession } from ../server/auth; import { type GetServerSideProps } from next; export const getServerSideProps: GetServerSideProps async (ctx) { const session await getServerAuthSession(ctx); return { props: { session }, }; }; const User () { const { data: session } useSession(); // 注意session 不会再有 loading 状态因为它已在服务端预取 ... }该辅助函数内部封装了getServerSession——它是仅运行在服务端的函数不会触发多余的网络请求这是它优于传统getSession的关键点export const getServerAuthSession async (ctx: { req: GetServerSidePropsContext[req]; res: GetServerSidePropsContext[res]; }) { return await getServerSession(ctx.req, ctx.res, nextAuthOptions); };App Router 写法对应当前仓库模板在当前的 src/server/auth/index.ts 模板中create-t3-app 导出了一个经过react的cache()包装的auth辅助函数可直接在 Server Component 或 Route Handler 中异步调用import { auth } from ~/server/auth; export default async function Home() { const session await auth(); ... }模板源码揭示了它的实现细节——使用cache()包装以避免在单次渲染中重复执行认证逻辑import NextAuth from next-auth; import { cache } from react; import { authConfig } from ./config; const { auth: uncachedAuth, handlers, signIn, signOut } NextAuth(authConfig); const auth cache(uncachedAuth); export { auth, handlers, signIn, signOut };从这里可以看到模板同时导出了handlers供app/api/auth/[...all]/route.ts使用、signIn与signOut构成完整的认证 API 面。将user.id注入 Session 对象默认情况下NextAuth.js 的会话对象只包含user.name、user.email、user.image等少数字段不含数据库主键id。create-t3-app 通过配置 session callback 把用户 ID 注入session对象callbacks: { session({ session, user }) { if (session.user) { session.user.id user.id; } return session; }, },同时配合一个类型声明文件确保通过session.user.id访问时具备完整的类型提示。这正是 NextAuth.js 文档中所谓的 Module Augmentation模块扩充import { DefaultSession } from next-auth; declare module next-auth { interface Session { user?: { id: string; } DefaultSession[user]; } }在当前仓库模板中这段 Module Augmentation 已经内置在 config/base.ts 里并且额外支持继续扩展role等自定义字段源码中保留了注释占位declare module next-auth { interface Session extends DefaultSession { user: { id: string; // ...other properties // role: UserRole; } DefaultSession[user]; } }安全提示同样的模式可以用来给session对象添加任何其他数据如role角色字段但绝不应滥用它在客户端存储敏感数据如密码、令牌等因为会话数据对客户端是可见的。与 tRPC 集成构建受保护的 API 过程将 NextAuth.js 与 tRPC 结合你可以借助 tRPC 的 middleware 机制创建可复用、仅限已认证用户访问的受保护过程procedure。create-t3-app 已为你配置好这一切。整个过程分为两步第一步将会话注入 tRPC Context利用getServerSession从请求头中取出会话而不是每个过程内重复导入 auth options再通过辅助函数把会话传入 tRPC contextimport { getServerAuthSession } from ../common/get-server-auth-session; export const createContext async (opts: CreateNextContextOptions) { const { req, res } opts; const session await getServerAuthSession({ req, res }); return await createContextInner({ session, }); };在 App Router 模板中对应的实现位于server/api/trpc.ts直接调用auth()import { auth } from ~/server/auth; import { db } from ~/server/db; export const createTRPCContext async (opts: { headers: Headers }) { const session await auth(); return { db, session, ...opts, }; };第二步创建校验登录态的 middleware 与 protectedProcedure创建一个检查用户是否已认证的 tRPC middleware并用它定义protectedProcedure。任何调用这些过程的请求必须已认证否则抛出UNAUTHORIZED错误由客户端妥善处理export const protectedProcedure t.procedure.use(({ ctx, next }) { if (!ctx.session?.user) { throw new TRPCError({ code: UNAUTHORIZED }); } return next({ ctx: { // 将 session 推断为非空类型 session: { ...ctx.session, user: ctx.session.user }, }, }); });注意中间件中通过next({ ctx: {...} })重新构造了上下文TypeScript 会据此将后续ctx.session.user推断为非空你无需再手动做空值判断。实战用 user.id 查询数据库会话对象是对用户的轻量、最小化表示只包含少量字段。在protectedProcedure中你可以拿到ctx.session.user.id用它去数据库查询更完整的数据const userRouter router({ me: protectedProcedure.query(async ({ ctx }) { const user await prisma.user.findUnique({ where: { id: ctx.session.user.id, }, }); return user; }), });这就是 T3 应用受保护 API → 按用户 ID 取数的典型链路。与 Prisma / Drizzle 集成数据库适配器让 NextAuth.js 与 Prisma 协同工作需要大量初始配置。create-t3-app 已全部替你处理完毕——如果你同时勾选 Prisma或 Drizzle与 NextAuth.js会得到一个带有全部必需数据模型的完整可用认证系统。预置的 Prisma 数据模型在 with-auth.prisma 中四个认证必需的模型已就绪Account、Session、User、VerificationToken。其中User模型如下model User { id String id default(cuid()) name String? email String? unique emailVerified DateTime? image String? accounts Account[] sessions Session[] posts Post[] }Account与Session通过onDelete: Cascade与User建立外键关系并带有unique([provider, providerAccountId])等约束。当前仓库模板通过 config/with-prisma.ts 将PrismaAdapter(db)挂载到 authConfig 上export const authConfig { providers: [DiscordProvider], adapter: PrismaAdapter(db), callbacks: { session: ({ session, user }) ({ ...session, user: { ...session.user, id: user.id, }, }), }, } satisfies NextAuthConfig;如果你选择 Drizzle则 config/with-drizzle.ts 会改为挂载DrizzleAdapter并显式传入四个表的引用adapter: DrizzleAdapter(db, { usersTable: users, accountsTable: accounts, sessionsTable: sessions, verificationTokensTable: verificationTokens, }),给认证模型添加新字段时必须提供默认值当你向User、Account、Session或VerificationToken中的任一模型添加新字段时大多数场景只需改User必须牢记Prisma/Drizzle 适配器会在新用户注册、登录时自动在这些模型上创建记录而适配器并不感知你新加的字段。因此新增字段必须提供默认值否则写入会失败。例如想给User模型加一个role角色字段 enum Role { USER ADMIN } model User { ... role Role default(USER) }default(USER)保证适配器自动创建用户记录时该字段有合法值。与 Next.js Middleware 结合JWT 会话策略的注意事项在 Next.js 12 中保护一组页面最直接的方式是使用 middleware 文件。但 NextAuth.js 与 Next.js middleware 协同使用要求采用 JWT 会话策略middleware 只能访问 JWT 形式的会话 cookie。而create-t3-app 默认配置的是数据库database会话策略配合 Prisma 作为数据库适配器。如果你确实需要 middleware需要切换为 JWT 策略并同步修改sessioncallback——此时user对象是undefined必须改从token对象取用户 IDexport const authOptions: NextAuthOptions { session: { strategy: jwt, }, callbacks: { - session: ({ session, user }) ({ session: ({ session, token }) ({ ...session, user: { ...session.user, - id: user.id, id: token.sub, }, }), }, }安全提示数据库会话是官方推荐的做法。切换 JWT 策略前请务必先充分阅读 JWT 相关文档避免引入安全风险。同时不应单独依赖 middleware 做授权——尽量在靠近数据读取的位置再次校验会话。配置默认的 DiscordProvidercreate-t3-app 预置了 Discord OAuth Provider选择它是因其上手门槛最低——只需在.env中填入令牌即可。配置步骤如下前往 Discord 开发者门户的 Applications 板块点击 New Application新建应用在设置菜单中进入 OAuth2 General复制Client ID粘贴到.env的AUTH_DISCORD_ID在 Client Secret 处点击Reset Secret重置密钥将生成的字符串粘贴到.env的AUTH_DISCORD_SECRET。⚠️ 该密钥只显示一次且重置会使旧密钥立即失效点击Add Redirect添加重定向地址粘贴app url/api/auth/callback/discord。本地开发示例http://localhost:3000/api/auth/callback/discord保存更改。其他建议开发与生产环境不建议共用同一个 Discord 应用虽然技术上可行开发阶段也可以考虑 mock Provider 以加速联调。关于环境变量AUTH_SECRET、AUTH_DISCORD_ID、AUTH_DISCORD_SECRET的占位符由 CLI 的 envVars.ts 注入到.env/.env.example# Next Auth AUTH_SECRET # Next Auth Discord Provider AUTH_DISCORD_ID AUTH_DISCORD_SECRET且 create-t3-app 会通过crypto.getRandomValues自动生成一个随机的AUTH_SECRET写入本地.env带有# Generated by create-t3-app.注释而.env.example保留空值// Generate an auth secret and put in .env, not .env.example const secret Buffer.from( crypto.getRandomValues(new Uint8Array(32)) ).toString(base64);你随时可用npx auth secret重新生成密钥。新增环境变量时记得同步更新src/env.js的校验 schema参见环境变量指南。添加更多 Provider添加其他 OAuth Provider 也很简单按 NextAuth.js 的 providers 文档操作即可。需要留意的是某些 Provider 要求给特定模型增加额外字段——例如模板注释中提到的 GitHub Provider 需要在Account模型上增加refresh_token_expires_in字段with-auth.prisma 中已预置该列。因此务必阅读所用 Provider 的文档确认拥有全部必需字段。实用资源资源说明NextAuth.js 文档https://next-auth.js.org/NextAuth.js GitHubhttps://github.com/nextauthjs/next-authtRPC Kitchen Sink含 NextAuth 示例https://kitchen-sink.trpc.io/next-auth仓库内可继续深入阅读的相关材料当前认证模板源码src/server/auth/index.ts、config/base.ts、config/with-prisma.ts、config/with-drizzle.ts预置 Prisma 认证模型with-auth.prisma环境变量生成逻辑cli/src/installers/envVars.ts相关文档tRPC 使用指南、Prisma 使用指南、上手第一步总结create-t3-app 将 NextAuth.js 的复杂性封装进了脚手架SessionProvider 让客户端随处取会话getServerAuthSession/auth()辅助函数让服务端取会话零样板代码session callback Module Augmentation 让session.user.id完全类型安全tRPC middleware 让受保护过程一行即得Prisma/Drizzle 适配器与数据模型开箱即用。掌握这套链路后你在 T3 应用中搭建从登录到鉴权再到按用户取数的完整后端只需专注于业务本身。赞分享开发工具CLI代码生成【免费下载链接】create-t3-appThe best way to start a full-stack, typesafe Next.js app项目地址https://gitcode.com/gh_mirrors/cr/create-t3-app点击查看免费下载相关推荐create-t3-app 中的 NextAuth.js 集成指南从 Session 注入到 tRPC 鉴权的完整实践create t3 app 中的 NextAuth.js 集成指南从 Session 注入到 tRPC 鉴权的完整实践 本文是一份面向 create t3 a开发工具CLI代码生成create-t3-app 的 NextAuth.js 集成实战指南会话管理、tRPC 保护过程与 Discord OAuth 配置create t3 app 的 NextAuth.js 集成实战指南会话管理、tRPC 保护过程与 Discord OAuth 配置 导读 当你在 Next.开发工具CLI代码生成create-t3-app 中的 NextAuth.js 集成指南从会话上下文到受保护路由的完整实战create t3 app 中的 NextAuth.js 集成指南从会话上下文到受保护路由的完整实战 本篇技术指南聚焦 create t3 app 脚手架对开发工具CLI代码生成上一篇PlayIntegrityFix终极配置手册快速解决设备认证问题下一篇LayerZero V2消息库MessageLib详解自定义DVN和Executor实现指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表