前言

之前使用了crypto-js做了一个md5加密用户密码的操作,但是由于该库本身没有提供比对方法,于是自己去实现了一个方法,而且还需要自己提供一个唯一值盐。

最近发现bcrypt这个库更好用,于是改用它了。

安装依赖

pnpm i bcrypt
pnpm i @types/bcrypt -D

教程

原来使用crypto-js的MD5方法,需要自己提供盐(salt),之前的做法是创建一个环境变量,然后预设一个定死的string字符串,这就导致我们需要维护一份唯一值的盐,有点麻烦。

bcrypt自身可以生成盐,并且它的盐会通过某些方式存储在加密后的字符串上,然后比对的时候,我们不需要知道之前它的盐是什么,它自己会从加密后的string中取,然后再去比对,所以非常方便。

.env.development

# hash-saltOrRounds
HASH_SALT_OR_ROUNDS="12"

我们在环境变量文件中创建一个变量,这个变量表示生成的盐的位数,推荐在10-12之间,可以保证一个很好的性能和加密效果,如果位数过多,会导致hash的时候耗时非常长。

然后我们调整之前auth.service.ts服务

import { BadRequestException, Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { RegisterDto } from "./dto/register.dto";
import { LoginDto } from "./dto/login.dto";
import { PrismaService } from "src/prisma/prisma.service";
import { JwtService } from "@nestjs/jwt";
import type { User } from "@prisma/client";
import { hash, compare } from "bcrypt";

@Injectable()
export class AuthService {
    constructor(
        private readonly prisma: PrismaService,
        private readonly config: ConfigService,
        private readonly jwtService: JwtService
    ) {}

    /** 注册账号 */
    async register(data: RegisterDto) {
        const { email, password } = data;
        const user = await this.prisma.user.create({
            data: {
                email,
                password: await hash(password, Number(this.config.get("HASH_SALT_OR_ROUNDS")))
            }
        });

        return this.generateToken(user);
    }

    /** 登录 */
    async login(data: LoginDto) {
        const { email, password } = data;

        // 查找用户
        const findUser = await this.prisma.user.findFirst({
            where: {
                email
            }
        });

        // 比对密码
        const isMatch = await compare(password, findUser.password);
        if (!isMatch) {
            throw new BadRequestException("密码错误");
        }

        return this.generateToken(findUser);
    }

    /** 生成token */
    private async generateToken({ id, email }: User) {
        return {
            token: await this.jwtService.signAsync({
                sub: id,
                email: email
            })
        };
    }
}

bcrypt引入hash、compare方法,hash方法第二个参数如果是number类型的值,它会自己去生成指定位数的盐,所以我们从环境变量取到HASH_SALT_OR_ROUNDS后进行一个Number转换。

compare传入两个参数,第一个是未加密前的值,第二个是加密后的值,它自己会去比对,原来后之前封装的md5里面的verify方法差不多。

bcrypt库同时还提供了同步的方法,后缀是带Sync的,大家可以根据自己需要使用。

分类: Nest.js 标签: 加密哈希Nestjsbcrypt散列

评论

暂无评论数据

暂无评论数据

目录