You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用typegraphql-prisma如何实现鉴权,避免用户删除他人Post资源

实现方案

typegraphql-prisma 完全支持通过中间件、resolver 增强的方式给自动生成的 CRUD resolver 加鉴权逻辑,不需要手动重写整套 mutation 代码,以下是两种常用实现方式:

方案1:使用applyResolversEnhanceMap绑定权限守卫(官方推荐)

这是 typegraphql-prisma 专门提供的扩展能力,可以针对单个模型的单个操作绑定自定义校验逻辑,侵入性最低。

  • 首先编写自定义的 Post 所有者校验守卫,里面可以获取 GraphQL 上下文中的当前登录用户信息、请求入参,完成所有者校验:
import { Guard, IGuardArgument } from "@typegraphql/prisma";
import { Context } from "./context"; // 你的上下文类型,包含当前登录用户、prisma实例等

export class PostOwnerGuard implements Guard<Context> {
  async canActivate({ context, args }: IGuardArgument<Context>) {
    // 先判断用户是否登录
    const currentUserId = context.currentUser?.id;
    if (!currentUserId) return false;
    // 获取要操作的Post ID
    const targetPostId = args.where.id;
    // 查库获取目标Post的所有者ID
    const targetPost = await context.prisma.post.findUnique({
      where: { id: targetPostId },
      select: { authorId: true }
    });
    if (!targetPost) return false;
    // 校验是否是所有者
    return targetPost.authorId === currentUserId;
  }
}
  • 然后在初始化自动生成 resolver 的文件中,用applyResolversEnhanceMap为 deletePost 操作绑定这个守卫即可:
import { applyResolversEnhanceMap, ResolverActionsConfig } from "@typegraphql/prisma";
import { PostOwnerGuard } from "./post-owner.guard";

const postResolverConfig: ResolverActionsConfig<"Post"> = {
  // 给删除、更新操作都加所有者校验
  deletePost: [UseGuard(PostOwnerGuard)],
  updatePost: [UseGuard(PostOwnerGuard)]
};

applyResolversEnhanceMap({
  Post: postResolverConfig
});

配置完成后,所有针对 Post 的删除、更新请求都会先走守卫的校验逻辑,非所有者的请求会直接被拦截,你也可以在校验不通过时自定义返回值,比如直接返回 null。

方案2:使用全局 GraphQL 中间件统一拦截

如果你需要给所有模型的修改、删除操作都加类似的所有者校验,可以用全局中间件统一处理,不需要逐个配置每个模型的守卫:

  • 编写全局中间件:
import { MiddlewareFn } from "type-graphql";
import { Context } from "./context";

export const OwnerCheckMiddleware: MiddlewareFn<Context> = async ({ context, info, args }, next) => {
  const operationName = info.fieldName;
  // 只拦截删除、更新类操作
  if (operationName.startsWith("delete") || operationName.startsWith("update")) {
    const currentUserId = context.currentUser?.id;
    if (!currentUserId) throw new Error("未授权访问");
    // 提取操作的模型名
    const modelName = operationName.replace(/delete|update/, "").toLowerCase();
    // 查库获取目标资源的所有者ID,这里可以根据不同模型调整关联用户的字段名
    const targetRecord = await context.prisma[modelName].findUnique({
      where: args.where,
      select: { authorId: true, userId: true }
    });
    const ownerId = targetRecord?.authorId || targetRecord?.userId;
    if (ownerId && ownerId !== currentUserId) {
      // 校验不通过可以抛错或者直接返回null
      throw new Error("无权限操作该资源");
    }
  }
  return next();
};
  • 在构建 Schema 的时候注册全局中间件即可:
import { buildSchema } from "type-graphql";

const schema = await buildSchema({
  resolvers: [/* 你的所有resolver,包括自动生成的CRUD resolver */],
  globalMiddlewares: [OwnerCheckMiddleware]
});

如果有特殊场景需要自定义逻辑,你也可以直接覆盖自动生成的对应 mutation resolver,自己编写完整的校验和业务逻辑,和普通自定义 resolver 的写法完全一致。

内容的提问来源于stack exchange,提问作者dsmurl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 07:24:03