1. Hash
- 해킹과 같은 위험에 대비하게 위해 암호를 hash 할거임
- hash는 일방향 함수이며 문자열이 필요
- https://www.npmjs.com/package/bcrypt
- 우리는 DB에 암호를 그냥 저장하지 않고, 해싱된 암호를 저장
bcrypt
A bcrypt library for NodeJS.. Latest version: 5.1.1, last published: a year ago. Start using bcrypt in your project by running `npm i bcrypt`. There are 7172 other projects in the npm registry using bcrypt.
www.npmjs.com
- 해커가 해싱된 암호를 가지고 공격을 하는걸 rainbow table이라고 하는데, 그걸 막기 위해 bcrypt를 사용
bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) {
// Store hash in your password DB.
});
- 말 그대로 소금을 뿌린다는 것으로, 더욱 암호를 예측하기 어렵게 함
- 암호가 저장되기 전에 해싱을 할건데, 이전에 pre("save")를 썼던 적이 있으니 그걸 다시 활용
// User.js
userSchema.pre("save", async function () {
this.password = await bcrypt.hash(this.password, 5);
});
- 상기시켜보면, this.password는 당연하게도 create는 user를 가리킴
- 소금칠 횟수는 5회
- await을 사용했으므로 callback function은 필요 없음
User PW: 22
Hash PW: $2b$05$rhD5E1s67tRe9KbHTr5Oju43PIoswqYOdqwGjGDgFRoh2rWCF22.6
- 비번이 알아먹지 못하게 잘 해싱 되었음
2. Controller 수정
- 암호를 해싱했지만, 반대로 유저가 로그인하고 싶을 때 어떻게 암호가 일치하는지 확인하는지는 로그인 때 알아볼 예정
- 지금 문제는 이미 저장된 이름이나 메일로 추가적인 회원가입을 할 경우 무한로딩이 걸리며 duplicate key error 에러가 발생
- 우리는 User.js에 unique를 줬음
- await을 써서 입력한 username을 가진 유저가 있는지 확인
export const postJoin = async (req, res) => {
const { email, username, password, name, location } = req.body;
const userNameExists = await User.exists({ username });
if (userNameExists) {
return res.render("join", {
pageTitle: "Join",
errorMessage: "This username is already taken.",
});
}
const emailExists = await User.exists({ email });
if (emailExists) {
return res.render("join", {
pageTitle: "Join",
errorMessage: "This Email is already taken.",
});
}
await User.create({
email,
username,
password,
name,
location,
});
return res.redirect("login");
};
- 이렇게 만들 수 있지만, 중복되는 코드가 많음
- https://www.mongodb.com/ko-kr/docs/manual/reference/operator/query/or/
$or - MongoDB 매뉴얼 v8.0
$text 이 페이지에서는 자체 관리형(Atlas에서 관리하지 않는) 배포를 위한 일반 텍스트 쿼리 기능을 제공합니다. MongoDB Atlas에서 호스팅되는 데이터의 경우 MongoDB는 향상된 전체 텍스트 쿼리 솔루
www.mongodb.com
- 이럴때 사용하는 것이 $or operator
const userNameExists = await User.exists({ username, email });
- 이 방법은 username과 email이 동시에 중복되는 계정만 찾기 때문에 사용하기 힘듦
export const postJoin = async (req, res) => {
const { email, username, password, name, location } = req.body;
const exists = await User.exists({ $or: [{ username }, { email }] });
if (exists) {
return res.render("join", {
pageTitle: "Join",
errorMessage: "This username/email is already taken.",
});
}
await User.create({
email,
username,
password,
name,
location,
});
return res.redirect("login");
};
- 훨씬 깔끔해지고, 추가적인 중복 데이터들을 막아 낼 수 있음 - 그리고 우리가 흔히 회원가입할 때 봤던, 비밀번호를 두번에 걸쳐 확인하는 과정도 추가해야 함
if (password1 !== password2) {
return res.render("join", {
pageTitle: "Join",
errorMessage: "Password confirmation does not match.",
});
}
- 실제 회원가입을 생각하면 여전히 문제가 발생할 부분들이 있지만 수정은 추후에 할 예정
'개발 > Node.js' 카테고리의 다른 글
Login / Bcrypt Compare (0) | 2024.11.08 |
---|---|
Status Code (0) | 2024.11.08 |
User Model (0) | 2024.11.07 |
Delete and Search Video (0) | 2024.11.05 |
Mongoose Middleware(2) (0) | 2024.11.04 |