해싱(Hashing)
해싱은 데이터의 효율적인 저장과 검색을 위해 사용되는 알고리즘입니다. 해시 함수를 사용하여 데이터를 해시 테이블에 저장하고, 동일한 해시 함수를 사용하여 데이터를 나중에 다시 검색할 수 있습니다. 해시 함수는 일정한 길이의 문자열(해시 값)을 생성하므로, 데이터의 길이에 상관없이 항상 일정한 크기의 데이터를 반환합니다.
이러한 해싱 작업을 수행하는데 도움을 주는 모듈이 `bcrypt` 입니다. 해당 글에서는 `Next.js`에서 어떻게 해싱을 하는지 알아 보도록 하겠습니다.
모듈 설치
npm i bcrypt
npm i -D @types/bcrypt
사용하기
해싱을 하는 곳은 대체로 회원가입하는 유저의 비밀번호 입니다. 회원가입시 유저의 비밀번호를 해싱하는 코드를 구현해 보겠습니다.
해싱
패스워드를 해싱하는 메소드
async hashPassword(password: string): Promise<string> {
const salt = await bcrypt.genSalt(10);
return await bcrypt.hash(password, salt);
}
요청에 따라 새로운 유저 객체를 만들어서 `DB`에 저장하는 서비스
async create(signUpReqDto: SignUpReqDto): Promise<User> {
await this.validateNewUser(signUpReqDto);
const hashedPassword = await this.hashPassword(signUpReqDto.password);
const createdUser = {
...signUpReqDto,
password: hashedPassword,
};
return this.userRepository.create(createdUser);
}
이제는 테스트를 해보겠습니다. 아래와 같은 객체로 회원가입이 요청이 왔다고 보겠습니다.
{
"name": "John Doe",
"email": "john.doe1@example.com",
"password": "Securepassword1",
"passwordConfirmation" : "Securepassword1"
}
패스워드가 해싱된 결과는 아래와 같습니다. 패스워드가 객체에서 보낸 값이 아닌 다른 값으로 저장된 것을 볼 수 있습니다.
{
"name": "John Doe",
"email": "john.doe1@example.com",
"password": "$2b$10$hLUdX6Zvcb95sPWuNpWkVO4x3u0JOByC9Gmtx5mRpHDPCpO9EhOIy",
"role": "user",
"_id": "6513deaa347d71fa239bc3de",
"createdAt": "2023-09-27T07:50:02.189Z",
"__v": 0
}
비교
로그인을 한다고 하면 해싱된 패스워드를 다시 비교하여야 하는 경우가 일 것입니다. 이렇게 바뀐 비밀번호를 어떻게 비교하여 검증하는지 알아보도록 하겠습니다.
아래의 코드는 로그인 시도를 하는 유저의 아이디를 가지고 `DB`에 데이터 존재여부를 확인하고 패스워드가 일치하는지 검증하는 메소드 입니다.
async validateUser(email: string, pass: string): Promise<User> {
const user = await this.userService.findOneByEmail(email);
if (!user) {
throw new BadRequestException({
message: ExceptionMassage.USER_NOT_FOUND,
at: 'AuthService.validateUser',
});
}
const isMatch = await bcrypt.compare(pass, user.password);
if (!isMatch) {
throw new BadRequestException({
message: ExceptionMassage.PASSWORD_NOT_MATCH,
at: 'AuthService.validateUser',
});
}
return user;
}
성공적으로 검증이 되었다면 유저에게 토큰을 제공하여 마무리 해줍니다.
async signIn(signInReqDto: SignInReqDto): Promise<SignInResDto> {
const validUser = await this.validateUser(
signInReqDto.email,
signInReqDto.password,
);
const { access_token } = await this.createToken(validUser);
return new SignInResDto(access_token);
}
'Backend > Nest.js' 카테고리의 다른 글
Nest.js Rate Limiting 설정 (0) | 2023.09.30 |
---|---|
Nest.js Swagger 보안 설정 (0) | 2023.09.30 |
Nest.js Module (0) | 2023.09.26 |
Nest.js Provider (0) | 2023.09.26 |
Nest.js Swagger Bearer 인증 적용 (1) | 2023.09.26 |