로그인 기능 만들기
우선 로그인을 하려면 요청된 이메일이 데이터베이스에 있는지 찾아야 한다.
그다음 요청된 비밀번호와 같은지 여부를 판단한다. 만약 둘 다 일치한다면 Token을 생성하면 된다.
이메일 확인하기
우선 엔드포인트는 './login'으로 하고 post 메서드를 하나 추가한다.
그 후 몽고DB 메서드인 findOne 메서드를 사용하여 일치하는 email을 찾는다. 만약 존재하지 않는다면 실패 메시지를 전달한다. 일치하는 email이 있다면 비밀번호를 비교한다.
app.post('/login', (req, res) => {
//요청된 이메일을 DB에서 찾는다
User.findOne({ email: req.body.email }, (err, user)=> {
if(!user){
return res.json({
loginSuccess: false,
message: "email이 일치하는 유저가 없습니다."
})
}
})
})
이는 User 모델에 함수를 하나 정의하여 비교하자.
평문으로 전달되는 비밀번호를 암호화(hash)된 비밀번호와 비교하여 일치여부를 확인해야 한다.
평문을 암호문으로 변경하기는 쉬우나 암호문을 복호화하기는 어렵기 때문에 평문을 암호화(hash)하여 비교한다.
이때 bcrypt의 compare 메서드를 이용하면 된다. 만약 err가 있다면 err를 return 하고 err가 없다면 isMatch(true)를 반환한다.
//비밀번호 비교
userSchema.methods.comparePassword = function(plainPassword, cb){
bcrypt.compare(plainPassword, this.password, function(err, isMatch){
if(err) return cb(err)
cb(null, isMatch)
})
}
email과 password가 일치하다면 Token을 생성하면 된다.
Token을 생성하려면 라이브러리가 하나 필요하다.
npm install jsonwebtoken --save
token을 만들 id와 string을 합쳐 token을 생성해주는 라이브러리이다.
이를 user 모델에 token부분에 저장하면 된다.
userSchema.methods.generateToken = function(cb){
var user = this;
//jsonwebtoken을 이용하여 token 생성
var token = jwt.sign(user._id, 'secretToken');
user.token = token
user.save(function(err, user){
if(err) return cb(err)
cb(null, user)
})
}
이제 라우터에서 password가 일치 여부를 확인한 이후 token을 생성하면 된다.
이때 생성된 token을 어딘가에 저장해야 하는데 쿠키에 저장하는 방법도 있고 로컬에 저장하는 부분도 있다.
지금은 쿠키에 저장을 해보자. 쿠키에 저장하기 위해서는 'cookie-parser'라이브러리를 설치해야 한다.
npm install cookie-parser --save
쿠키 이름을 설정하고 생성된 토큰(모델에 저장되어 있는)을 저장한 뒤, 성공 코드와 정보를 return 하면 된다.
//비밀번호 일치 여부 확인
user.comparePassword(req.body.password, (err, isMatch) =>{
if(!isMatch)
return res.json({loginSuccess: false, message: "비밀번호 불일치"})
//Token생성
user.generateToken((err, user) => {
if(err) return res.status(400).send(err)
//토큰을 저장(쿠기, 로컬, etc)
res.cookie("x_auth", user.token)
.status(200)
.json({ loginSuccess: true, userId: user._id })
})
})
전체 라우터 코드는 다음과 같다.
app.post('/login', (req, res) => {
//요청된 이메일을 DB에서 찾는다
User.findOne({ email: req.body.email }, (err, user)=> {
if(!user){
return res.json({
loginSuccess: false,
message: "email이 일치하는 유저가 없습니다."
})
}
//비밀번호 일치 여부 확인
user.comparePassword(req.body.password, (err, isMatch) =>{
if(!isMatch)
return res.json({loginSuccess: false, message: "비밀번호 불일치"})
//Token생성
user.generateToken((err, user) => {
if(err) return res.status(400).send(err)
//토큰을 저장(쿠기, 로컬, etc)
res.cookie("x_auth", user.token)
.status(200)
.json({ loginSuccess: true, userId: user._id })
})
})
})
})
이제 직접 로그인을 해보자.
서버를 동작시키고 다음과 같이 postman으로 send 하면 된다.
결과는 다음과 같다.