티스토리 뷰

728x90
반응형

가장 기본이지만 필자에게는 제일 어려웠던 로그인 기능을 오늘 추가해보려고 한다.

전체적인 개념은 이해했지만 아직도 무언가 부족한 느낌이 들었지만, 오늘도 어느 정도 이해를 바탕으로 글을 쓰려고 한다.

 

 

 

1. 데이터 베이스에서 요청한 E-mail을 찾기

일단 회원가입이 되어있는지의 E-mail을 찾는 코드가 필요하다.

Express 라우트 메소드를 사용한다.

// POST method route
app.post('/', function (req, res) {
  res.send('POST request to the homepage');
});

mongodb에서 제공하는 method를 이용한다.

//index.js
...
app.post('/login', (req, res) => {
  User.findOne({ email: req.body.email }, (err, user) => {
    if(!user) {
      return res.json({
        loginSuccess: false,
        message: "제공된 이메일에 해당하는 유저가 없습니다."
      })
    }
  })
})
...

만약 user이 참이 아닌 경우 res.json으로 리턴한다. 리턴할 때는 로그인은 실패하였고, 실패 메시지를 보낸다는 의미이다.

 

2. 요청된 이메일이 있을 때, 비밀번호가 맞는지 확인하기

// index.js
app.post('/login', (req, res) => {
  ...
    user.comparePassword(req.body.password, (err, isMatch) => {
      if(!isMatch)
        return res.json({loginSuccess: false, message: "비밀번화 틀렸습니다."})
    })
  })
})

임의로 원하는 compoarePassword메소드를 생성하여, 맞지 않으면 비밀번호 오류 메시지를 클라이언트에 전송한다. 여기서 argument 두 개 중 하나는 req.body.password로 회원가입 시 입력한 비밀번호로 의미하며, callback function값으로 err값 혹은 비밀번호가 맞는지를 가져오게 된다.

 

3. userSchema.methods.compoarePassword를 생성

// moduls/User.js
...
userSchema.methods.comparePassword = function(plainPassword, cb) {
    //plainPassword ex) 1234567 암호화된 비밀번호 ex)$2b$10$... 가 같은지 체크
    bcrypt.compare(plainPassword, this.password, function(err, isMatch) {
        if(err) return cb(err);
        cb(null, isMatch)
    })
}
...

여기에서 plainPassword는 일반적인 비밀번호이며, 현재 데이터베이스에 저장된 암호화된 비밀번호를 비교를 해야한다. 암호화된 비밀번호를 복호화를 할 수 없기에 plainPassword를 암호화하여 this.password(암호화된 비밀번호 = 데이터베이스에 저장된 비밀번호)를 비교한다.

 

4. 비밀번호가 동일하면 토큰을 생성하기

그전에 jsonwebtoken, cookie-parser라는 라이브러리를 설치한다.

yarn add jsonwebtoken cookie-parser

jsonwebtoken사이트를 참조하여 토큰을 생성한다.

// moduls/User.js
...
const jwt = require('jsonwebtoken');

userSchema.methods.generateToken = function(cb){
    let user = this;
    let token = jwt.sign(user._id.toHexString(), 'secretToken')

    user.token = token;
    user.save(function(err, user) {
        if(err) return cb(err)
        cb(null, user)
    })  
}

jwtwebtoken을 먼저 import를 해준 후 sign을 이용한다. 여기서 user._id와 secretToken값을 넣어야 token이 생성이 되기 때문에 두 가지의 값을 알아야 한다.

generateToken을 한 후 만약 에러가 있을 때, 에러메세지와 400 포트를 전달한다.

//index.js
...
const cookieParser = require('cookie-parser');
...
app.use(cookieParser());
...

app.post('/login', (req, res) => {
	...
      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})
      })
	...
})

에러가 없는 경우, 토큰을 쿠키에 저장한다.

여기에서 x_auth는 관리자모드의 Application에서 Cookies에 x_auth가 하나 생성이 된다. 명칭은 자유롭게 바꿀 수 있는 듯하다.

여기에서는 쿠키와 로컬 스토리지에 대한 보완성이 더 좋은지에 대한 논란이 많아 일단 여기서는 쿠키로 저장하였다. 이렇게 하면 로그인 라우트를 모두 마친 것이다. 실제로 확인을 해보기 위해 postman을 연 후 라우터는 register에서 login으로 바꾼 후 확인을 한다.

postman에서 로그인이 되는지 확인

아직 완벽한 이해가 부족하여 설명이 두리뭉실하거나 이해하는데 어려움이 있을 것이다. 오늘 공부한 내용은 깃허브에 올릴 것이며 참고하시길 바란다.

 

 

깃허브 코드 확인하기

 

참고사이트

TMI

다시 공부하면서 새로 알게 된 내용을 적게 되었다. 이전에 body-parser도 express 미들웨어에 이미 있어 설치 없이 진행이 가능했다. 그리고 혹시나 궁금하여 cookie-parser을 찾아보니 이 또한 생략이 가능하게 express에 포함이 되어있었다.

그래서 위와 같이 진행을 한 후 다음과 같은 일부를 생략할 수 있다. 또한 cookie-parser 또한 설치를 하지 않아도 된다.

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

 

더보기

21. 03. 25 첫 업데이트

21. 05. 10 TMI 추가 설명 업로드

728x90
반응형
댓글
250x250
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
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
글 보관함