NestJS-bcrypt加密解密使用
NestJS-bcrypt加密解密使用
1、认识安装
在 NestJS 中使用 bcrypt
来进行密码哈希和验证是非常常见的需求。bcrypt
是一个安全的哈希算法,它可以用于加密用户密码,并且提供了验证密码是否匹配的功能。
👉安装 bcrypt
首先,你需要安装 bcrypt
库。使用以下命令进行安装:
npm install bcrypt
// 这里我使用的版本是 "bcrypt": "^5.1.1",
如果你使用的是 TypeScript,bcrypt
可能还需要安装类型定义文件,这里我的
npm install @types/bcrypt --save-dev
//yarn方式安装
yarn add @types/bcrypt --save-dev
// 版本
"@types/bcrypt": "^5.0.2",
2、使用 bcrypt
👉作用
没有经过加密之前我们的密码是这样的
1111111111
加密以后我们的密码
$10$D1L8Dh3L1NKTUaJsvr.7r./dm6p19ix7e7ZwctuMZ1KzdTbEk1muO
之前我们的密码都是明文存储的,接下来我们就加密解密对于密码进行验证
user.password = registerDto.password;
👉注册迁移到auth模块
之前我们注册模块在user模块之中,接下来我们迁移到auth授权模块
auth.controller.ts
import { RegisterDto } from '@/utils/response.dto';
@Post('register')
register(@Body() registerDto: RegisterDto) {
return this.authService.register(registerDto);
}
auth.module.ts引入用户实体
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from '@/modules/user/user.entity';
@Module({
imports: [
TypeOrmModule.forFeature([User]), // 注册 User 实体
],
providers: [AuthService, JwtStrategy],
controllers: [AuthController],
})
export class AuthModule {}
auth.service.ts
import { InjectRepository } from '@nestjs/typeorm';
import { RegisterDto } from '@/utils/response.dto';
import { User } from '@/modules/user/user.entity';
// 异步注册方法
async register(registerDto: RegisterDto) {
// 查询数据库中是否存在同名用户
const existingUser = await this.userRepository.findOne({ where: { username: registerDto.username } });
// 如果存在同名用户,则抛出异常
if (existingUser) {
versionhello('用户注册提示', '用户已存在!');
// throw new ConflictException('用户已存在!');
// return {
// data: [],
// message: '用户已存在!',
// code: 400,
// };
throw new HttpException(
{
code: 400, // 适当的错误码是 400
message: '用户已存在!',
},
HttpStatus.BAD_REQUEST, // 使用 400 状态码
);
}
// 创建新用户
const user = new User();
user.username = registerDto.username;
user.password = registerDto.password;
// user.password = hashedPassword;
const savedUser = await this.userRepository.save(user); // 保存到数据库
console.log(savedUser, 'savedUser');
// 返回注册成功的信息
return {
message: '恭喜你,您的账号注册成功!',
code: 200,
};
}
3、加密解密
👉加密
正确引入迁移以后,接下来就可以针对密码进行加密和解密了
加密
//导入
import * as bcrypt from 'bcrypt';
async hashPassword(password: string): Promise<string> {
const salt = await bcrypt.genSalt(10); // 生成 salt
const hashedPassword = await bcrypt.hash(password, salt); // 用 salt 加密密码
return hashedPassword;
}
// 加密密码
const hashedPassword = await this.hashPassword(registerDto.password);
//直接使用
user.password = hashedPassword;
加密以后得密码
$2b$10$D1L8Dh3L1NKTUaJsvr.7r./dm6p19ix7e7ZwctuMZ1KzdTbEk1muO
👉解密
加密完以后这个时候我们的密码已经入库,接下来在解密部分反翻译出密码对比,这部分在登录这里实现
// 验证密码
async validatePassword(password: string, hashedPassword: string): Promise<boolean> {
const isMatch = await bcrypt.compare(password, hashedPassword); // 比较密码
return isMatch;
}
完善auth.service.ts
//对比密码
const isPasswordValid = await
this.validatePassword(LoginDto.password, loginUser.password);
//简单对比一下用户的账号密码信息
if(isPasswordValid){
return {
message: '登录成功!',
code: 200,
token: token,
};
}else{
return {
message: '用户名或密码错误!',
code: 400,
};
}
4、完整示例
整个过程
注册时加密密码:注册时,使用 bcrypt.hash() 加密密码,与盐值一起生成哈希密码。
登录时验证密码:登录时,使用 bcrypt.compare() 方法比较输入的密码和数据库中存储的哈希密码。
盐值的轮数:bcrypt.genSalt() 方法的 saltRounds 参数控制了生成盐值的复杂度
常见的值是 10,如果需要更强的加密,可以增加该值。
完整的用户注册时使用 bcrypt
对用户密码进行加密
在服务层(如 AuthService
)中处理密码的加密和验证
👉示例
AuthService
中使用 bcrypt
auth.service.ts
(加密和验证密码)
typescriptCopy Codeimport { Injectable } from '@nestjs/common';
import * as bcrypt from 'bcrypt';
import { RegisterDto } from './dto/register.dto';
@Injectable()
export class AuthService {
private readonly saltRounds = 10; // 加密的盐值轮数,通常设为10或更高
// 加密密码
async hashPassword(password: string): Promise<string> {
const salt = await bcrypt.genSalt(this.saltRounds); // 生成盐值
return await bcrypt.hash(password, salt); // 生成加密密码
}
// 验证密码
async validatePassword(password: string, hashedPassword: string): Promise<boolean> {
return await bcrypt.compare(password, hashedPassword); // 比较原密码和哈希密码
}
// 用户注册的逻辑
async register(registerDto: RegisterDto): Promise<string> {
const { password } = registerDto;
const hashedPassword = await this.hashPassword(password); // 将密码加密
// 假设保存用户数据到数据库,通常会在这里调用 Repository 或 ORM 方法保存
console.log('Hashed Password:', hashedPassword);
return 'User registered successfully';
}
}
register.dto.ts
typescriptCopy Codeimport { IsString, IsEmail, IsNotEmpty, MinLength } from 'class-validator';
export class RegisterDto {
@IsString()
@IsNotEmpty()
@MinLength(3)
username: string;
@IsEmail()
@IsNotEmpty()
email: string;
@IsString()
@IsNotEmpty()
@MinLength(6)
password: string;
}
auth.controller.ts
(使用 AuthService
)
typescriptCopy Codeimport { Body, Controller, Post } from '@nestjs/common';
import { AuthService } from './auth.service';
import { RegisterDto } from './dto/register.dto';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Post('register')
async register(@Body() registerDto: RegisterDto) {
return await this.authService.register(registerDto); // 调用 AuthService 中的 register 方法
}
}
- 使用
bcrypt
验证密码
在用户登录时,你会需要将用户输入的密码与数据库中存储的哈希密码进行比较。这是通过 bcrypt.compare()
方法来实现的,它会对输入的密码进行哈希并与存储的哈希进行比较。
在上面的 AuthService
中,已经提供了一个 validatePassword
方法来验证密码是否正确。这个方法使用 bcrypt.compare()
来比较输入密码和哈希密码。
在 AuthService
中验证密码
typescriptCopy Code// 在 AuthService 中验证密码
async login(loginDto: LoginDto): Promise<string> {
const { email, password } = loginDto;
// 假设从数据库中获取用户的哈希密码
const user = await this.userRepository.findOne({ where: { email } });
if (!user) {
throw new Error('User not found');
}
// 使用 bcrypt 比较密码
const isPasswordValid = await this.validatePassword(password, user.password);
if (!isPasswordValid) {
throw new Error('Invalid credentials');
}
return 'Login successful';
}
通过以上方法,NestJS 中就能安全地加密和验证用户的密码了。
- 点赞
- 收藏
- 关注作者
评论(0)