使用 Prisma 2 从查询中排除用户密码

Vas*_*jis 3 rest node.js prisma prisma2

最近我开始做一个新项目来学习一些新技术(Prisma 2、带有 Express 的 REST api 等)。不过,我遇到了一个问题。

我的应用程序有一个用户身份验证系统,并且用户模型有一个密码列。因此,当客户端请求用户时,后端会从数据库中选择所有列,包括密码(顺便说一下,密码是经过哈希处理的)。

我尝试不选择 prisma findMany 上的密码列,如下所示:

await prisma.user.findUnique({
  where: {
    ...
  },
  select: {
    password: false
  }
});
Run Code Online (Sandbox Code Playgroud)

但我收到了 prisma 的一个错误,说选择应该至少包含一个真正的值。因此,我添加id: true到选择中。我发出了一个 api 请求,我看到只有 id 返回给用户。

据我了解,prisma 希望我将所有我关心的列添加到选择对象中。但是,我需要来自用户的大量列,并且我正在进行大量查询来获取用户,而且我不能每次都编写我需要的所有字段。

所以,我想问你是否有合法的方法可以做到这一点。

PS:我不采取“使用 rawQuery 代替”作为解决方案。

Ale*_*uck 7

我也一直想知道如何实现这一点,令人困惑的是@Ryan 帖子中链接的问题已经有两年多了,而且仍未解决。我想出了一个临时解决方法,即为 Prisma 客户端实现一个中间件功能,在每次调用后手动删除密码字段。

import { PrismaClient } from '@prisma/client'

async function excludePasswordMiddleware(params, next) {
  const result = await next(params)
  if (params?.model === 'User' && params?.args?.select?.password !== true) {
    delete result.password
  }
  return result
}

const prisma = new PrismaClient()
prisma.$use(excludePasswordMiddlware)
Run Code Online (Sandbox Code Playgroud)

这将检查正在查询的模型是否为User,并且如果您使用选择查询显式包含密码,则不会删除该字段。这应该允许您在需要时仍然获得密码,例如当您需要对正在登录的用户进行身份验证时:

async validateUser(email: string, password: string) {
  const user = await this.prisma.user.findUnique({
    where: { email },
    select: {
      emailVerified: true,
      password: true,
    },
  })
  // Continue to validate user, compare passwords, etc.
  return isValid
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上,我认为最有效的方法(特别是当您使用它作为 API 响应时)是使用 [class-transformer](https://github.com/typestack/class-transformer)。使用它,您可以为用户创建一个 DTO 类,该类不会公开密码字段等内容。然后,使用 plainToClass 函数将用户实体(来自 Prisma 并包含密码)转换为用户 DTO 类(不包含用户密码)。这就是您摆脱密码的方法。检查一下图书馆,它非常酷,它让我的事情变得简单多了。 (2认同)

Rya*_*yan 6

唯一合法的方法是添加column: true到您想要包含的列。这里有一些排除列的请求,因此如果您可以在与您相关的请求中添加一个,以便我们可以查看优先级,那就太好了。

https://github.com/prisma/prisma/issues/5042 https://github.com/prisma/prisma/issues/7380 https://github.com/prisma/prisma/issues/3796