티스토리 뷰
[node js - express 쇼핑몰 웹] 3. 로그인, 로그아웃, 회원가입 구현하기
무니웜테일패드풋프롱스 2020. 7. 16. 15:38📌2020 07 16
- login, sign up, 그리고 resetting password 구현
- sign up과 resetting password에서는 gmail api를 이용하여 user에게 email을 보내도록 함
✨how "sign up" works
-
사용자에게 email과 password를 입력받는다.
-
email이 이미 존재하면 다른 페이지로 리다이렉트 해준다.
-
email 존재하지 않는다면 새로운 User 모델을 생성하고 데이터베이스에 반영해준다.
-
sign up이 완료되면 gmail api 를 이용하여 User에게 sign up이 되었다고 알려준다.
exports.postSignUp=(req,res,next)=>{ const email = req.body.email; const password = req.body.password; // 해당 email 이 존재하면 fail User.findOne({email:email}) .then(user=>{ if(!user){ // 이메일 사용 가능 return bcrypt.hash(password,12) .then(hashedPassword=>{ // hashed password로 변경 const user = new User({ email:email, password:hashedPassword, cart:{items:[]} }); // 새로운 User 데이터 저장 user.save() .then(result=>{ res.redirect('/login'); sendMail(email,'welcome to Amadoo!', `<h1>Thank you for signing in our shopping mall 'AMADOO' </h1> <p> we hope you'll get bunch of great exprience in our shop</p> <p> if you have any troubles while shopping, please let us know by this email! </p> `); }) }).catch(err=>console.log(err)); } else{ res.redirect('/signUp'); } }) .catch(err=>console.log(err)); }
✨how " login " works
-
사용자로부터 email 과 password를 입력받는다.
-
받은 email로 해당하는 User데이터를 찾고, password를 bcrypt.compare()로 비교해준다.
-
일치할 시 로그인하고 req.session.user에 user를 저장해준다.
exports.postLogin=(req,res,next)=>{ const email = req.body.email; const password=req.body.password; User.findOne({email:email}) .then(user=>{ if(!user){ //유저 아이디 맞지 않는 경우 res.redirect('/login'); } else{ bcrypt.compare(password,user.password) .then(doMatch=>{ if(!doMatch){ // 비밀번호가 맞지 않는 경우 res.redirect('/login'); } else{ req.session.isLoggedIn= true; // 로그인 되었음 req.session.user = user; // 유저 정보 저장 req.session.save(err=>{ // 세션 저장 console.log(err); res.redirect('/'); // password 체크하는 flow 추가해줘야함 }) } }) .catch(err=>console.log(err)); } }).catch(err=>console.log(err)); }
- 어플리케이션 전역에서 User 모델에 접근 할 수 있어야 하므로 req.session.user!== undefined라면 req.user에 해당 User모델을 담아준다.
app.use((req,res,next)=>{
if(req.session.user){ // session.user가 저장되었다면 == 로그인 되었다면
User.findOne(req.session.user._id) // 해당user찾기
.then(user=>{
req.user = user; // req.user에 저장해서 전역에서 접근 가능하도록
next();
})
.catch(err=>console.log(err));
}
else{
next();
}
})
✨logout
-
로그아웃을 하면 session이 destroy 된다.
exports.getLogout=(req,res,next)=>{ // 로그아웃 req.session.destroy(); res.redirect('/'); }
✨how resetting password works
-
사용자로부터 resetting password를 할 email을 입력받아 온다.
-
해당 email로 난수 token을 쿼리값으로 준 path를 전송한다.
exports.postNewPassword=(req,res,next)=>{ // password 재설정 post // 토큰 값을 포함한 path를 email 로 발송해준후 리다이렉트. const email = req.body.email; crypto.randomBytes(32, (err,Buffer)=>{ // 토큰 생성 if(err){ console.log(err); return res.redirect('/new-password'); } const token = Buffer.toString('hex'); User.findOne({email:email}) // 유저 찾기 .then(user=>{ if(!user){ return res.redirect('/reset'); } user.resetToken=token; // 해당 유저에 토큰 및 만기일 저장 user.resetTokenExpiration= Date.now()+3600000; return user.save(); }) .then(result=>{ res.redirect('/'); // 이메일 보내기 return sendMail(email, 'Reset your password', ` follow <a href="http://localhost:3000/new-password/${token}">this link</a> to reset your password `); }) .catch(err=>console.log(err)); }) }
-
해당 path에는 파라미터 값으로 담아온 토큰을 추출하여 해당 토큰을 저장한 User모델을 찾도록 한다.
-
User모델을 찾았으면 post request로 새로 입력 받은 password와 함께 토큰 값, User Id를 넘긴다.
exports.getResetPage=(req,res,next)=>{ const token = req.params.token; // 파라미터 User.findOne({resetToken:token, resetTokenExpiration:{$gt: Date.now()}}) // User 모델 찾기 .then(user=>{ if(!user){ res.redirect('/');} // User가 존재하지 않는다면 리다이렉트 else{ res.render('auth/reset-password', { path:'/reset-password', pageTitle:'reset password', userId:user._id, resetToken:token }) } }) .catch(err=>console.log(err)); }
-
post 라우팅에서는 req.body에 담아온 user Id와 token을 통해 해당 User의 token이 아직 만료되지 않았는지 다시한번 확인한다.
-
만료되지 않았고 정삭적으로 User 모델을 찾으면 req.body에 담아온 password를 hash값으로 변경하여 User모델에 저장해주고 데이터베이스에 반영해준다.
exports.postResetPage=(req,res,next)=>{
const token = req.body.token;
const userId= req.body.userId;
const password =req.body.password;
let foundUser;
User.findOne({_id:userId, resetToken:token, resetTokenExpiration:{$gt: Date.now()}})
.then(user=>{
if(!user){ // user 존재하지 않음
res.redirect('/');
}
else{
foundUser = user;
return bcrypt.hash(password,12)
.then(hashedPassword=>{
foundUser.password=hashedPassword;
foundUser.resetToken=undefined;
foundUser.resetTokenExpiration=undefined;
return foundUser.save();
})
}
})
.then(result=>{
res.redirect('/login');
})
.catch(err=>console.log(err));
}
'Project > 첫번째 프로젝트 쇼핑몰 웹' 카테고리의 다른 글
[ node js - express 쇼핑몰 웹] 6. Cart 와 Order 수량 변경 기능 구현 / Cart 내에서 체크한 항목만 Order하는 기능 구현 (0) | 2020.07.22 |
---|---|
[ node js - express 쇼핑몰 웹] 5. Seller 등록, 취소 구현 (0) | 2020.07.22 |
[ node js - express 쇼핑몰 웹 ] 4. input data validation 추가 (0) | 2020.07.19 |
[node js - express 쇼핑몰 웹] 2. 삭제된 product 정보 cart와 order에 적용시키기 (0) | 2020.07.15 |
[node js - express 쇼핑몰 웹] 1. Mongo DB 설정 (0) | 2020.07.15 |