[모두의 이력서_5일차] Bcrypt로 비밀번호 암호화 하기
처음으로 혼자서 프론트부터 백까지 하는 프로젝트이다 보니 정확하지 않을 수 있습니다!
Bcrypt로 비밀번호 암호화 하기
현재 DB에 저장된 비밀번호 보면 너무 안전하지 않습니다.
몽고디비 컴패스를 보면 비밀번호가 그대로 나와 있다는 것을 알 수 있습니다.
그래서 Bcrypt를 이용해서 비밀번호를 암호화해줘서 데이터베이스에 저장해줘야 합니다.
1. Bcrypt 설치하기
npm install bcrypt --save
npm install -D @types/bcrypt // 타입스크립트 사용하는 경우
2. Bcrypt로 비밀번호 암호화 하는 순서
https://www.npmjs.com/package/bcrypt?activeTab=readme
bcryptjs
Optimized bcrypt in plain JavaScript with zero dependencies. Compatible to 'bcrypt'.. Latest version: 2.4.3, last published: 6 years ago. Start using bcryptjs in your project by running `npm i bcryptjs`. There are 3002 other projects in the npm registry us
www.npmjs.com
유저 정보들 (Account, Password 등등)을 데이터 베이스에 저장하기 전이 암호화 할 타이밍
// server.ts
// 회원가입 라우터
app.post("/register", async (req, res) => {
const user = new User(req.body);
// save하기전에 암호화를 해줘야 된다.
const result = await user
.save()
.then(() => {
res.status(200).json({
success: true,
});
})
.catch((err: "empty") => {
res.json({ success: false, err });
});
return result;
});
1. 기본틀 작성
// User.ts
const bcrypt = require('bcrypt');
.
.
.
// pre는 몽그스 메소드
// save를 해주면 유저 정보를 저장하기 전에(server.ts save전) 무언가를 한다는 것이다.
serSchema.pre("save", function (next) {
// 할꺼 다하고 끝나면
next(); // server.ts의 save로 보낸다.
});
2. soltRounds = 10;
saltRounds : salt가 몇 글자인지 나타낸다.
// User.ts
const bcrypt = require('bcrypt');
const saltRounds = 10;
.
.
.
serSchema.pre("save", function (next) {
bcrypt.genSalt(saltRpunds, function(errm salt){ // salt 만들기
})
next();
});
3. salt를 먼저 생성
여기서 myPlaintextPassword는 암호화된 password가 아닌 순수하게 작성한 password를 가리킵니다.
그러므로 userSchema의 password를 가져오면 됩니다.
// User.ts
const bcrypt = require('bcrypt');
const saltRounds = 10;
const userSchema = new Schema({
.
.
.
})
serSchema.pre("save", function (next) {
const user = this; // userSchema를 가리킴
bcrypt.genSalt(saltRpunds, function(err, salt){
if(err) return next(err)
// salt를 제대로 생성했다면
// user.password라고 하면 userSchema의 password로 넣은 값
bcrypt.hash(user.password, salt, function (err, hash){ // hash는 암호화된 비밀번호
}
})
next();
});
user.password라고 하면 userSchema의 password로 넣은 값을 가져올 수 있습니다.
password: 1234로 넣었으면 1234를 가지고 옵니다.
4. salt를 이용해서 비밀번호 암호화 하기
// User.ts
const bcrypt = require('bcrypt');
const saltRounds = 10;
const userSchema = new Schema({
.
.
.
})
serSchema.pre("save", function (next) {
const user = this;
bcrypt.genSalt(saltRpunds, function(err, salt){
if(err) return next(err)
bcrypt.hash(user.password, salt, function (err, hash){
// 에러 발생할 경우 server.ts에 있는 save로 보내기
if (err) return next(err);
// 암호화된 비밀번호를 만드는데 성공했으면 유저의 순수비밀번호를 암호화한 비밀번호로 교체
user.password = hash;
next();
}
})
next();
});
3. 비밀번호 변환될 때만 bcrypt 발동
사이트를 이용하다 보면 비밀번호를 변경할 때도 있고, 사용자 이름, 이메일을 변경하는 경우가 생깁니다.
무언가 변경해서 새로 저장할 때마다 bcrypt부분이 계속 변경하게 됩니다.
즉 비밀번호가 아니라 이메일만 바꿀 때에도 다시 비밀번호를 암호화해버립니다.
그러므로 조건을 걸어줘야 됩니다.
// User.ts
const bcrypt = require('bcrypt');
const saltRounds = 10;
const userSchema = new Schema({
.
.
.
})
userSchema.pre("save", function (next) {
const user = this;
// 비밀번호를 변환될때만 bcrypt발동
if (user.isModified("password")) {
// 비밀번호를 암호화 시킨다.
bcrypt.genSalt(saltRounds, function (err, salt) {
if (err) return next(err);
if (!user.password) return null;
bcrypt.hash(user.password, salt, function (err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
});
}
});
export const User = model("User", userSchema);
4. 비밀번호 말고 다른걸 바꾸는 경우 next()해주기
// User.ts
const bcrypt = require('bcrypt');
const saltRounds = 10;
const userSchema = new Schema({
.
.
.
})
userSchema.pre("save", function (next) {
const user = this;
// 비밀번호를 변환될때만 bcrypt발동
if (user.isModified("password")) {
// 비밀번호를 암호화 시킨다.
bcrypt.genSalt(saltRounds, function (err, salt) {
if (err) return next(err);
if (!user.password) return null;
bcrypt.hash(user.password, salt, function (err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
});
} else { // 비밀번호를 바꾸는게 아니라면 즉 다른거를 바꾸라면 -> 만약 없으면 계속 userSchema에 머무르게 된다.
next(); // server.ts save로 보내기
}
});
export const User = model("User", userSchema);
npm run start
포스트맨에 보내고 몽고디비컴패스에 확인하면
암호화가 잘되었다. 끝-!
require → import
User.ts
import { Schema, model, Model } from "mongoose";
import bcrypt from "bcrypt";
const saltRounds = 10;
const userSchema = new Schema({
name: {
type: String,
maxlength: 50,
},
email: {
type: String,
trim: true,
unique: 1,
},
password: {
type: String,
minlength: 5,
},
lastname: {
type: String,
maxlength: 50,
},
role: {
type: Number,
default: 0,
},
image: String,
token: {
type: String,
},
tokenExp: {
type: Number,
},
});
userSchema.pre("save", function (next) {
const user = this;
// 비밀번호를 변환될때만 bcrypt발동
if (user.isModified("password")) {
// 비밀번호를 암호화 시킨다.
bcrypt.genSalt(saltRounds, function (err, salt) {
if (err) return next(err);
if (!user.password) return null;
bcrypt.hash(user.password, salt, function (err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
});
}
});
export const User = model("User", userSchema);
참고자료
https://www.youtube.com/watch?v=XonyJxSDoGE