简介

所有的数据库中,对密码的保存永远不是明文的,这是一种常识,我们使用Nestjs和Prisma创建用户时也是一样的,对用户的密码也不是明文的。

有些教程使用argon2库来加密密码,但是这个库在windows上永远是安装失败,为此直接放弃使用它,改用crypto-js,来实现相同功能。

教程

先安装依赖:

pnpm i crypto-js @types/crypto-js

然后我们封装一个简单的工具文件:md5.ts

import { MD5 } from "crypto-js";

/**
 * @description: hash加密
 * @param {string} val 要加密的字符串
 * @param {*} salt 盐
 * @Date: 2024-01-02 07:33:26
 * @Author: mulingyuer
 */
export function hash(val: string, salt = "") {
    return MD5(`${val}${salt}`).toString();
}

/**
 * @description: 比对加密后的字符串
 * @param {string} val 要比对的字符串
 * @param {string} hashVal 加密后的字符串
 * @param {*} salt 盐
 * @Date: 2024-01-02 07:35:22
 * @Author: mulingyuer
 */
export function verify(val: string, hashVal: string, salt = "") {
    return hash(val, salt) === hashVal;
}

这里我们使用了salt盐,它的作用就是增加密码的难度,假设我的密码是123456,但是我的盐是:u9Uo9ibS9N@9tZ,将它们进行组合。

123456u9Uo9ibS9N@9tZ

u9Uo9ibS9N@9tZ123456

再将它们转换成MD5值,你会得到一个很难破解的加密值,如果你没有我的盐,那么基本上无法正确解密出密码,通过这种方式我们就可以很安全的存储用户的密码,且不是一个明文的。

当然我们还有很多复杂的加密方式,这取决于你的项目需要的安全程度,但是逻辑上都是相同的。

盐怎么配置

盐可以是一段自己随便输入的字符串,推荐是:英文+数字+符号,越长越复杂,越难破译。

我们可以将其存储在环境变量中,在Nestjs中,我们通过@nestjs/config加载环境变量,具体可以查看《Nestjs与Prisma多环境变量文件解决方案》这篇文章。

假设我们的环境变量:

.env.development

# md5-salt
MD5_SALT="u9Uo9ibS9N@9tZ"

使用

import { BadRequestException, Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { LoginDto, RegisterDto } from "src/dto/auth.dto";
import { PrismaService } from "src/prisma/prisma.service";
import { hash, verify } from "../utils/md5";

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

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

    /** 登录 */
    async login(data: LoginDto) {
        const { email, password } = data;
        const md5Salt: string = this.config.get("MD5_SALT");

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

        // 比对密码
        if (!verify(password, findUser.password, md5Salt)) {
            throw new BadRequestException("密码错误");
        }

        return findUser;
    }
}

通过this.config.get("MD5_SALT")我们可以获取到环境变量中的盐,然后使用它。

再通过hashverify方法实现加密和比对。

分类: Nest.js 标签: 密码加密crypto-jsNestjsMD5

评论

暂无评论数据

暂无评论数据

目录