如何优化TypeScript-Next.js Server Actions的会话校验结构
统一处理Server Actions的会话校验方案
问题背景
我有多个Server Actions(比如createProduct、getProductAssets等),目前每个Action在请求时都会先校验用户会话的有效性。我希望只执行一次会话校验,通过后再调用目标函数,请问该如何组织product-actions/index文件的结构?以下是其中一个函数示例:
export async function getProductAssets(productId: string) { try { const session: Session = await getServerSession(authOptions); if (!session.user) { return { success: false, message: 'Unauthorized!', }; } // 后续业务逻辑... } catch (error) { // 错误处理... } }
解决方案:用高阶函数统一封装校验逻辑
把会话校验逻辑抽离成一个通用的包装函数(高阶函数),所有需要校验的Server Actions都通过这个函数包裹,实现一次校验复用。
具体实现结构(product-actions/index.ts)
import { getServerSession } from "next-auth/next"; import { authOptions } from "../auth/[...nextauth]"; // 根据你的项目路径调整 import type { Session } from "next-auth"; // 通用会话校验包装函数 async function withAuth<T extends (...args: any[]) => Promise<any>>( handler: (session: Session, ...args: Parameters<T>) => ReturnType<T> ): T { return async (...args: Parameters<T>) => { try { const session = await getServerSession(authOptions); // 校验会话有效性 if (!session?.user) { return { success: false, message: 'Unauthorized!' }; } // 校验通过,执行业务逻辑并传入会话信息 return handler(session, ...args); } catch (error) { return { success: false, message: 'Session verification failed' }; } } as T; } // --- 业务逻辑函数(仅处理核心业务,无需重复写校验)--- async function getProductAssetsHandler(session: Session, productId: string) { // 这里写原本的getProductAssets业务逻辑 // 比如从数据库查询产品资产 return { success: true, data: [/* 资产数据示例 */] }; } async function createProductHandler(session: Session, productData: { name: string; price: number }) { // 创建产品的核心逻辑,可利用session中的用户信息做权限控制 return { success: true, productId: 'prod-123' }; } // --- 导出经过校验包装的Server Actions --- export const getProductAssets = withAuth(getProductAssetsHandler); export const createProduct = withAuth(createProductHandler);
优势说明
- 代码复用:避免在每个Server Action中重复写会话校验代码,减少冗余。
- 统一维护:后续若要修改校验规则(比如增加角色权限校验),只需修改
withAuth函数,无需逐个调整业务Action。 - 权限传递:业务逻辑函数可直接拿到
session,方便做更细粒度的权限控制(比如判断用户是否有权限操作当前产品)。
内容的提问来源于stack exchange,提问作者Fatih Can
相关产品推荐
相关产品推荐

