본문 바로가기
Web/React Node js

노드 기초 강의 (9) - 로그인 기능 with Bcrypt & 토큰 생성 with JSON WEBTOKEN

by SeleniumBindingProtein 2022. 2. 27.
728x90
반응형

1. 로그인 기능 만들기 수선

  1) 데이터베이스에서 요청한 E-mail 찾기 (.findOne() 메서드 이용하기)

  2) 데이터베이스에서 요청한 E-mail이 있다면 비밀번호가 같은지 확인

      (Bcrypt 이용해서 plain password와 암호화된(Hashed) 패스워드가 같은지 확인)

  3) 비밀번호까지 같다면 Token을 생성

      (토큰 생성을 위해서 JSON WEBTOKEN 라이브러리를 다운로드)

 

2. DB에서 요청한 E-mail 찾기

  1) .findOne()이란

      - 몽고DB 메서드로 데이터를 검색할 때 사용됨.

      - find()를 통해 데이터를 찾을 수 있지만, 여러 데이터 중에서 하나의 객체만 찾고 싶을 때 .findOne() 사용함

app.post('/login', (req, res) => {
    //요청된 이메일을 데이터베이스에서 있는지 찾음
    User.findOne({email: req.body.email}, (err, user)=>{
        if(!user){
            return res.json({
                loginSuccess: false,
                message: "제공된 이메일에 해당하는 유저가 없습니다."
            })
        }
    })
})

 

3. 요청한 E-mail이 비밀번호가 같은지 확인

  1) User 모델에 메서드 생성

      - 이전 Bcrypt로 비밀번호를 해싱시켰기 때문에, 비밀번호가 같은지 확인하려면

         Plain Password도 해시하여 DB의 암호화된 Password와 같은지 비교해야 함

  2) Bcrypt.compare() 사용

      - Bcrypt.compare() 메서드를 사용하면 쉽게 해결할 수 있고,

         이 메서드는 로그인을 위해 입력한 패스워드랑 DB에 저장되어있던 해싱된 패스워드가 유효한지 확인해줌

brcypt.compare(plainPassword, /*해쉬된 패스워드*/);

      - 새로 입력한 패스워드가 기존 해싱시킨 패스워드와 같으면 true, 아니면 false로 반환함 

userSchema.methods.comparePassword = function(plainPassword, cb){
    //plainPassword 비밀번호와 암호화된 비밀번호이 같은지 확인해야 함
    bcrypt.compare(plainPassword, this.password, function(err, isMatch){
        if(err) return cb(err);
            cb(null, isMatch)
    })
}

      - Register Route로 돌아와서 User 모델이 생성한 메서드로 응답메세지 생성

app.post('/login', (req, res) => {
    //요청된 이메일을 데이터베이스에서 있는지 찾음
    User.findOne({email: req.body.email}, (err, user)=>{
        if(!user){
            return res.json({
                loginSuccess: false,
                message: "제공된 이메일에 해당하는 유저가 없습니다."
            })
        }
        //요청된 이메일이 데이터베이스에 있다면 비밀번호가 맞는지 확인
        user.comparePassword(req.body.password, (err, isMatch) => {
            if(!isMatch)
                return res.json({loginSuccess: false, message: "비밀번호가 틀렸습니다."})
        })
    })
})

 

4. 비밀번호가 같다면 Token 생성

      - 토큰 생성을 위해서 JSON WEBTOKEN 라이브러리 다운로드

npm install jsonwebtoken --save

      - JWT USAGE

 

https://www.npmjs.com/package/jsonwebtoken

 

jsonwebtoken

JSON Web Token implementation (symmetric and asymmetric). Latest version: 8.5.1, last published: 3 years ago. Start using jsonwebtoken in your project by running `npm i jsonwebtoken`. There are 18352 other projects in the npm registry using jsonwebtoken.

www.npmjs.com

  1) User모델에 JWT 메서드 생성

userSchema.methods.generateToken = function(cb){
    
    var user = this;

    //jsonwebtoken을 이용해서 token을 생성
    var token = jwt.sign(user._id.toHexString(), 'secretToken') 

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

 

  2) Save Token 

      - Register Route로 돌아와서 User모델에 생성한 메시지로 토큰을 생성하고 저장함

      - Token은 보통 쿠키나 로컬스토리지에 저장하는데, 쿠키에 저장하기 위해서 cookie parser 라이브러리를 다운

npm install cookie-parser --save

      - Import Cookie-Parser

const express = require('express')
const app = express()
const port = 6660
const cookieParser = require('cookie-parser');
const config = require('./config/key');

const bodyParser = require('body-parser');
//application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: true}));
//application/json
app.use(bodyParser.json());

const {User} = require("./models/User");
app.use(cookieParser());

      - 토큰생성하고 저장하기 

app.post('/login', (req, res) => {
    //요청된 이메일을 데이터베이스에서 있는지 찾음
    User.findOne({email: req.body.email}, (err, user)=>{
        if(!user){
            return res.json({
                loginSuccess: false,
                message: "제공된 이메일에 해당하는 유저가 없습니다."
            })
        }
        //요청된 이메일이 데이터베이스에 있다면 비밀번호가 맞는지 확인
        user.comparePassword(req.body.password, (err, isMatch) => {
            if(!isMatch)
                return res.json({loginSuccess: false, message: "비밀번호가 틀렸습니다."})
            
            //비밀번호까지 맞다면 토큰 생성
            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})
            })
        })
    })
})

 

 

[결과 출력]

728x90
반응형

댓글