티스토리 뷰

📌2020 07 16

  • login, sign up, 그리고 resetting password 구현
  • sign up과 resetting password에서는 gmail api를 이용하여 user에게 email을 보내도록 함

✨how "sign up" works

  1. 사용자에게 email과 password를 입력받는다.

  2. email이 이미 존재하면 다른 페이지로 리다이렉트 해준다.

  3. email 존재하지 않는다면 새로운 User 모델을 생성하고 데이터베이스에 반영해준다.

  4. 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

  1. 사용자로부터 email 과 password를 입력받는다.

  2. 받은 email로 해당하는 User데이터를 찾고, password를 bcrypt.compare()로 비교해준다.

  3. 일치할 시 로그인하고 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));
    }
    
    1. 어플리케이션 전역에서 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

  1. 사용자로부터 resetting password를 할 email을 입력받아 온다.

  2. 해당 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));
     })
    }
  3. 해당 path에는 파라미터 값으로 담아온 토큰을 추출하여 해당 토큰을 저장한 User모델을 찾도록 한다.

  4. 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));
    }
    
  5. post 라우팅에서는 req.body에 담아온 user Id와 token을 통해 해당 User의 token이 아직 만료되지 않았는지 다시한번 확인한다.

  6. 만료되지 않았고 정삭적으로 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));
}
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함