Home 로그인 기능, 로그아웃 기능(Node js)
Post
Cancel

로그인 기능, 로그아웃 기능(Node js)

Compare password method

1
2
3
4
5
6
7
8
userSchema.methods.comparePassword = function (plainPassword, cb) {
  bcrypt.compare(plainPassword, this.password, function (err, isMatch) {
    if (err) {
      return cb(err);
    }
    cb(null, isMatch);
  });
};

사용자가 로그인 할 때 입력된 비밀번호와 DB의 암호화된 비밀번호를 비교해야 한다. comparePassword메소드를 만들어 준다. comparePassword메소드는 사용자가 로그인 시 입력한 plainPassword와 DB의 비밀번호를 비교한다. bcrypt.compare()는 true와 false를 반환하며, 비밀번호가 일치하면 true를 넘겨준다.

Login route and save token

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
32
33
app.post("/login", (req, res) => {
  // 요청된 이메일을 데이터 베이스에서 있는지 확인
  User.findOne({ email: req.body.email }, (err, user) => {
    if (!user) {
      return res.json({
        loginSuccess: false,
        message: "제공된 이메일에 해당하는 유저가 없습니다",
      });
    }
    // 요청한 이메일이 있으면 비밀번호 같은지 확인
    // (err, ##)은 callback function
    user.comparePassword(req.body.password, (err, isMatch) => {
      if (!isMatch) {
        // 비번이 틀렸을 때
        return res.json({
          loginSuccess: false,
          message: "비밀번호가 틀렸습니다.",
        });
      }
      user.generateToken((err, user) => {
        if (err) {
          res.status(400).send(err);
        }
        // 토큰을 저장한다 쿠키나 로컬저장소, session에 저장 가능
        // 쿠키에 저장
        res
          .cookie("x_auth", user.token)
          .status(200)
          .json({ loginSuccess: true, userId: user._id });
      });
    });
  });
});

사용자 로그인에도 POST방식이 사용된다. 먼저 findOne메소드로 데이터베이스에 이메일이 있는지 확인한 후 존재하면 비밀번호를 비교한다. 위에서 만든 comparePassword메소드를 사용하고, isMatch를 받는다. isMatch가 true이면 사용자 토큰을 생성하고 false이면 오류 메세지를 출력한다.

1
2
3
4
{
    "loginSuccess": true,
    "userId": "61d149633c6b8b24d75b5e7e"
}

postman으로 /login에서 테스트한 결과이다. 데이터베이스에 회원 정보가 존재 하는 것을 알 수 있다.

User Token

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
user.comparePassword(req.body.password, (err, isMatch) => {
  if (!isMatch) {
    // 비번이 틀렸을 때
    return res.json({
      loginSuccess: false,
      message: "비밀번호가 틀렸습니다.",
    });
  }
  user.generateToken((err, user) => {
    if (err) {
      res.status(400).send(err);
    }
    res
      .cookie("x_auth", user.token)
      .status(200)
      .json({ loginSuccess: true, userId: user._id });
  });
});

사용자가 로그인한 후 토큰을 만들어 저장해야 한다. 토큰은 cookie, session, local storage에 저장할 수 있다. 사용자 로그인 시 비밀번호가 일치하면 토큰을 저장한다. rescookie에는 cookie 이름과 사용자 토큰, status는 정상 동작을 의미하는 200을 포함해 전달한다.

토큰 생성에 필요한 의존성은 jsonwebtoken이고, cookie에 token을 저장하기 위한 의존성은 cookie-parser이다.

Auth

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// auth.js
let auth = (req, res, next) => {
  // 인증 처리 관리
  // 클라이언트 쿠키에서 토큰을 가져온다
  let token = req.cookies.x_auth;
  // 토큰을 복호화 한 후 유저를 찾는다
  User.findByToken(token, (err, user) => {
    if (err) throw err;
    if (!user) return res.json({ isAuth: false, error: true });

    req.token = token;
    req.user = user;
    // next의 이유는 middleware에서 더 진행할 수 있게 넣어준다
    next();
  });
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const jwt = require("jsonwebtoken");

userSchema.statics.findByToken = function (token, cb) {
  const user = this;

  // 토큰을 decode
  jwt.verify(token, "secreteToken", function (err, decoded) {
    // user id를 이요해서 user 찾은 다음에
    // 클라이언트에서 가져온 토큰과 DB에 보관된 토큰이 일치하는지 확인
    user.findOne({ _id: decoded, token: token }, function (err, user) {
      if (err) return cb(err);
      cb(null, user);
    });
  });
};

인증을 위해 middlewareauth.js를 생성해 인증을 관리한다. 사용자가 로그인을 한 후 화면을 이동할 때 사용자의 정보가 유효한지 확인해 줘야 한다. 토큰을 사용해 인증을 하며 사용자의 토큰은 cookie에 저장되어 있다.

jsonwebtoken을 이용해 클라이언트에서 가져온 토큰과 데이터베이스에 보관되어 있는 토큰이 일치하는지 확인한다.

로그아웃

1
2
3
4
5
6
7
8
app.get("/api/users/logout", auth, (req, res) => {
  User.findOneAndUpdate({ _id: req.user._id }, { token: "" }, (err, user) => {
    if (err) return res.json({ success: false, err });
    return res.status(200).send({
      success: true,
    });
  });
});

로그아웃 기능을 구현하기 위해 로그아웃 route를 만들었다. Route의 기능은 로그아웃 하려는 유저를 데이터베이스에서 찾아 해당 사용자의 토큰을 지워준다. 토큰은 위에서 페이지의 로그인 된 회원의 인증을 위해 사용되었기 때문에 토큰을 지우면 로그인을 하지 않은 상태와 같게 된다.

findOneUpdate함수를 사용해 로그아웃 하려는 사용자의 토큰을 지우고 업데이트 해준다.

Untitled

MongoDB의 사용자를 확인해보면 토큰이 ""으로 되어 있는 것을 볼 수 있다.

This post is licensed under CC BY 4.0 by the author.

Node js 프로젝트 시작하기

React 시작하기, Routing