资讯动态

NestJS Boilerplate 密码安全内幕:TypeORM ValueTransformer 实现 bcrypt 自动哈希的巧妙技巧

发布时间:2026/8/23 16:46:18 来源:尧图企业网站定制
NestJS Boilerplate 密码安全内幕TypeORM ValueTransformer 实现 bcrypt 自动哈希的巧妙技巧【免费下载链接】nestjs-boilerplateNestJS Boilerplate (Authentication, TypeORM, Configuration, Swagger)项目地址: https://gitcode.com/gh_mirrors/nes/nestjs-boilerplateNestJS Boilerplate 是一个内置 JWT 认证、TypeORM、Swagger 的 NestJS 后端脚手架它的用户密码从注册到落库全程不手动写一行哈希代码。本文带你拆解它如何用 TypeORMValueTransformer实现 bcrypt 自动哈希——这套技巧新手可以直接抄走老手也能学到防踩坑细节。一、为什么密码必须哈希存储把明文密码存进数据库是新手项目最常见的安全隐患之一数据库一旦泄露所有用户密码直接裸奔攻击者拿同一套明文密码可以撞库登录其他网站bcrypt是行业标准自带随机盐同一个密码每次哈希结果都不同且计算成本高能拖慢暴力破解。理想状态是开发者想都不用想密码就自动安全落库。这正是 NestJS Boilerplate 做的事。二、核心主角一个 12 行的 PasswordTransformer整个方案的灵魂在 password.transformer.tsexport class PasswordTransformer implements ValueTransformer { to(value) { return Hash.make(value); // 写入数据库前bcrypt 哈希 } from(value) { return value; // 从数据库读出原样返回 } }TypeORM 的ValueTransformer提供两个钩子方法触发时机本项目的行为to()实体写入数据库之前调用 bcrypt 哈希明文变密文from()数据读出数据库之后原样返回不做处理而哈希的具体实现封装在 Hash.tsstatic make(plainText) { const salt bcrypt.genSaltSync(); return bcrypt.hashSync(plainText, salt); }三、最巧妙的点from() 为什么什么都不做很多初学者的直觉是既然to()做哈希from()是不是也该做点什么答案恰恰相反这里的不对称设计才是精髓写入时to()把明文密码哈希成 bcrypt 密文数据库里永远只有$2b$10$...这样的字符串读取时登录验证需要执行bcrypt.compare(用户输入明文, 数据库密文)。如果from()再做任何加工读出来的值就不是真正的密文了比对必然失败所以from()直接返回原值——读出来的就是 bcrypt 密文本身正好是compare需要的第二个参数。一句话总结哈希只发生在写入瞬间读出时把密文原样交还给业务层去比对。四、完整链路注册 → 登录 → 返回密码全程隐身第 1 步注册自动哈希调用POST /api/auth/register时register.payload.ts 先校验邮箱格式、密码至少 5 位、passwordConfirmation必须与密码一致。随后服务层执行userRepository.save(payload)——TypeORM 在落库前自动调用to()明文密码瞬间变成哈希。开发者从头到尾没有调用过一次Hash.make完全透明。第 2 步登录密文比对auth.service.ts 中的验证逻辑if (!user || !Hash.compare(payload.password, user.password)) { throw new UnauthorizedException(Invalid credentials!); }这里的user.password得益于from()的原样返回正是数据库里的 bcrypt 密文与用户输入的明文密码比对验证通过则签发 JWT。第 3 步返回给前端双重移除密码字段拿到实体后还有两道保险确保密码密文也绝不出现在任何 API 响应中User实体重写了toJSON()序列化时直接解构剔除password字段jwt.strategy.ts 在签发 JWT 时再次剥离const { password, ...safeUser } user;五、一个容易被忽略的细节密码列为什么是 varchar(255)在 CreateUsersTable 迁移文件 中users表的password列定义为varchar(255)。bcrypt 默认输出 60 个字符255 的长度留足余量——如果照着网上的示例随手写成varchar(60)换成本项目这种带自定义盐轮数的场景就可能截断报错。六、如何在你的项目里抄走这套技巧三步即可复刻写一个Hash工具类封装bcrypt的make与compare写一个ValueTransformerto()里哈希from()里原样返回在实体的Column装饰器中传入transformer: new PasswordTransformer()参照 user.entity.tsColumn({ name: password, length: 255, transformer: new PasswordTransformer() }) password!: string;⚠️进阶避坑注意这个 transformer 只对从明文到入库的场景设计。如果你把已从数据库读出的实体password 已是密文再次save()回去to()会对密文二次哈希导致用户再也无法登录。修改密码时应先重新赋值明文而不是直接保存旧实体。七、快速上手 NestJS Boilerplategit clone https://gitcode.com/gh_mirrors/nes/nestjs-boilerplate cd nestjs-boilerplate ./initinit脚本会自动复制.env、生成强JWT_SECRET_KEY、拉起 Docker Compose 全家桶NestJS nginx MariaDB并执行 TypeORM 迁移。启动后访问http://localhost:8080即可调接口/api/docs打开 Swagger 文档亲测一遍 register → login 全流程就能亲眼看到密码自动哈希的效果。总结NestJS Boilerplate 用不到 30 行代码演示了一个优雅范式借助TypeORM ValueTransformer把存储格式bcrypt 密文与业务逻辑注册、登录彻底解耦to()哈希、from()透传的不对称设计是自动哈希能正确工作的关键toJSON() JWT 策略的双重字段剥离保证密文不泄露到前端。理解这套技巧后你以后在任何 TypeORM 项目中处理密码都只需要复制粘贴这三个文件的位置即可。【免费下载链接】nestjs-boilerplateNestJS Boilerplate (Authentication, TypeORM, Configuration, Swagger)项目地址: https://gitcode.com/gh_mirrors/nes/nestjs-boilerplate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价