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

Prisma迁移阶段执行数据转换脚本(如密码加密)的实现方案咨询

Prisma迁移阶段执行数据转换脚本(如密码加密)的实现方案咨询

嘿,刚好我之前处理过类似的Prisma密码迁移需求,给你梳理下可行的方案:

首先明确说一句:Prisma的原生迁移系统(不管是prisma migrate dev还是migrate deploy)并不直接支持在迁移流程中运行自定义的TypeScript/JS脚本——因为它的核心是处理SQL层面的Schema变更,没法直接嵌入业务逻辑类的转换操作。不过我们可以通过分步操作来实现你的需求,完全可控。

下面是针对你的场景的具体步骤:

1. 先扩展Schema,新增哈希密码字段

首先不要直接删掉原有的password明文字段,而是新增一个可选的hashedPassword字段来存储bcrypt哈希值(bcrypt生成的哈希通常是60位左右,所以设@db.VarChar(60)刚好)。修改后的User模型如下:

model User {
  id String @id @unique @db.Char(32) // unsigned UUID
  name String @unique @db.VarChar(16)
  password String @db.VarChar(32) // 暂时保留明文密码字段
  hashedPassword String? @db.VarChar(60) // 新增可选的哈希密码字段
  articles Article[]
  createdAt DateTime @default(now())
}

然后执行命令生成并运行迁移:

prisma migrate dev --name add-hashed-password-field

这一步会在数据库中新增hashedPassword字段,不会影响现有数据。

2. 编写自定义脚本,批量转换明文密码为哈希值

接下来我们写一个TypeScript脚本,用Prisma Client读取所有用户的明文密码,生成bcrypt哈希后更新到新字段。比如创建migrate-passwords.ts:

import { PrismaClient } from '@prisma/client';
import bcrypt from 'bcrypt';

const prisma = new PrismaClient();

async function migratePasswords() {
  // 只获取还没生成哈希密码的用户
  const users = await prisma.user.findMany({
    where: {
      password: { not: null },
      hashedPassword: null
    }
  });

  // 循环处理每个用户
  for (const user of users) {
    if (user.password) {
      // bcrypt默认用10轮盐值,这个参数可以根据需求调整
      const hashed = await bcrypt.hash(user.password, 10);
      await prisma.user.update({
        where: { id: user.id },
        data: { hashedPassword: hashed }
      });
      console.log(`已处理用户: ${user.name}`);
    }
  }

  console.log('所有密码哈希转换完成!');
  await prisma.$disconnect();
}

// 执行脚本并处理异常
migratePasswords().catch(async (err) => {
  console.error('转换过程出错:', err);
  await prisma.$disconnect();
  process.exit(1);
});

然后执行这个脚本:

npx ts-node migrate-passwords.ts

如果是JavaScript环境,直接用node migrate-passwords.js即可,记得先安装依赖bcrypt(或者bcryptjs,看你偏好)。

3. 验证业务逻辑切换

在删除原明文密码字段之前,一定要先修改你的业务代码——比如登录接口,把验证逻辑从对比明文密码,改成用bcrypt.compare()对比用户输入和hashedPassword字段。确认所有登录、用户相关的流程都能正常工作,再进行下一步。

4. 清理Schema和数据库字段

当你确认哈希密码完全可用后,就可以移除原有的password明文字段了。修改后的最终User模型:

model User {
  id String @id @unique @db.Char(32) // unsigned UUID
  name String @unique @db.VarChar(16)
  hashedPassword String @db.VarChar(60) // 现在设为必填字段
  articles Article[]
  createdAt DateTime @default(now())
}

然后生成并运行最终的迁移:

prisma migrate dev --name remove-plaintext-password-field

额外注意事项

  • 备份优先:执行任何数据变更前,一定要先备份数据库,避免操作失误导致数据丢失。
  • 批量优化:如果你的用户量很大,建议在脚本中加入分页逻辑(用skip和take),避免一次性加载所有用户导致内存溢出。
  • 生产环境流程:生产环境用prisma migrate deploy时,流程和本地一致:先部署新增字段的迁移,在服务器上执行密码转换脚本,验证后再部署移除原字段的迁移,尽量选低峰期操作。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 10:04:34