MongoDB 를 이용한 로그인/로그아웃 로직

Mono crom·2021년 3월 30일
0

로그인 로직은 아직 껄끄럽다.
스르륵 읽히는게 아니라 꾸역꾸역 눈에 집어넣어야 들어오는 느낌.
많이 짜보고 읽고 해서 백지상태에서도 흐름을 휙휙 만들어낼 수 있게 해야지.

로그인의 기본 로직은 이렇다.

  1. 클라이언트에서 email과 pw 정보가 req.body 에 담겨서 서버로 들어온다.
  2. User 테이블에서 해당 email을 가진 유저가 있는지 탐색
  3. 있으면, 해당 유저의 pw가 req의 pw와 일치하는지 확인
  4. 여기까지 ok면, 토큰을 생성
  5. 토큰을 쿠키에 담아서, { loginSuccess: true, userId: user.id } 객체로 200응답

이제 위의 로직이 실제 코드로는 어떻게 구현되는지 살펴보자.


큰 흐름


const cookieParser = require("cookie-parser");
app.use(cookieParser());

app.post("/api/users/login", (req, res) => {

  // 1. 요청받은 이메일을 DB에서 탐색
  User.findOne({ email: req.body.email }, (err, user) => {
    if (!user) {
      return res.json({
        loginSuccess: false,
        message: "not exist email",
      });
    }
    
    // 2. 이메일이 DB에 있다면, 비밀번호가 맞는 비밀번호인지 확인
    // comparePassword 와 generateToken 메소드는 다음 목차 확인
    user.comparePassword(req.body.password, (err, isMatch) => {
      if (!isMatch)
        return res.json({
          loginSuccess: false,
          message: "not matched password",
        });
      
      // 3. 비밀번호까지 맞다면, 토큰을 생성
      user.generateToken((err, user) => {
        if (err) return res.status(400).send(err);

        // 토큰을 저장한다. 어디에? 쿠키에...
        res
          .cookie("x_auth", user.token)
          .status(200)
          .json({ loginSuccess: true, userId: user._id });
      });
    });
  });
});

comparePassword & generateToken

위 로직에서 쓰였던 comparePassword 메소드와 generateToken 메소드는 이렇게 선언되어 있다.

// 나중에 comparePassword(plainPassword, cb) { ... } 이렇게 갖다쓰면 
// cb의 두 번째 인자에 true or false 값이 담겨서 { ... } 안에서 쓸 수 있음

userSchema.methods.comparePassword = function (plainPassword, cb) {
  // painPassword 를 암호화한 다음 db의 password와 비교
  // bcrypt.compare(기본 패스워드, 해싱된 패스워드, function(err, inMatch) { ... }
  bcrypt.compare(plainPassword, this.password, function (err, isMatch) {
    if (err) return cb(err);
    cb(null, isMatch);
  });
};

// --------------------------------------------------------------------------

// generateToken(err, user) { ... } 이렇게 갖다쓰면 
// user 에 토큰 딱 담겨서 { ... } 안에서 쓸 수 있게 됨
userSchema.methods.generateToken = function (cb) {
  var user = this;

  // jwt.sign(payload, secret_key) 에서 payload는 string 타입이어야 하는데,
  // mongoDB에서 자동생성되는 _id 는 string 타입이 아니므로 toHexString() 사용
  var token = jwt.sign(user._id.toHexString(), "secretToken");

  user.token = token;

  // 생성된 token을 해당 유저의 token칼럼에 담고 db에 save
  user.save(function (err, user) {
    if (err) return db(err);
    cb(null, user);
  });
};

로그아웃 로직

  • 작성 예정1
profile
니가 진짜로 원하는게 뭐야

0개의 댓글