ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Node.js] 로그인 / 토큰 생성 with JSON WEB TOKEN
    node.JS 2021. 12. 31. 23:52

     

     

    1. login route 만들기

      01 데이터베이스에서 요청한 E-mail 찾기 : mongodb 에서 제공하는 findOne 메소드 사용

    User.findOne({email:req.body.email},(err,user)=>{
             if(!user){
                 return res.json({
                     loginSucces:false,
                     message:"제공된 이메일에 해당하는 user가 없습니다."
                 })
             }

      02 DB 에서 요청한 E-mail 이 있다면 비밀번호가 같은지 확인, 비밀번호까지 같다면 Token 생성

     

    //user.js에서 comparePassword 메소드 만들기
    userSchema.methods.comparePassword = function(plainPassword,cb){
         //plainPassword를 암호화 해서 DB에 암호화되어 있는 password가 같은지 확인하기
         bcrypt.compare(plainPassword,this.password, function(err,isMatch){
             if(err) return cb(err),
             cb(null,isMatch) //password가 같을 때 err는 null이고 isMatch(true)이다.
         })
     }

    token생성 위해 JSONWEBTOKEN 라이브러리 다운

    npm install jsonwebtoken --save

    JSON WEB TOKEN (https://www.npmjs.com/package/jsonwebtoken)

    json을 임포트한 뒤 sign 메소드를 이용하여 합치면 token 생성 

     //user.js 에 generateToken 메소드 생성
     const jwt = require('jsonwebtoken');
     userSchema.methods.generateToken = function(cb){
         var user = this;
         console.log('user._id',user._id)
         //jsonwebtoken을 이용해서 token 생성
         var token = jwt.sign(user._id.toHexString(),'secretToken')
    
    	//user.id 와 'secretToken'을 합쳐 token을 만드는 것이다.
        //나중에 token을 해석할 때 secretToken 을 넣으면 user._id를 알 수 있다.
         
         user.token = token
         user.save(function(err,user){
             if(err) return cb(err);
             cb(null,user)
         })
     }

    token을 cookie에 저장하기 위해 tokenparser다운

    npm install cookie-parser --save
    const cookieParser = require('cookie-parser');
    app.use(cookieParser());
    //요청된 이메일이 DB에 있다면 PWD가 맞는 PWD인지 확인
    	user.comparePassword(req.body.password,(err,isMatch)=>{ //isMatch : db에 있는 pwd와 입력한 pwd가 일치
    		console.log('err',err)
    		if(!isMatch) //비밀번호가 틀렸을 경우
    			return res.json({loginSuccess: false, message:"비밀번호가 틀렸습니다."})
    
    		//비밀번호가 맞았을 경우. 토큰 생성
    		user.generateToken((err,user)=>{
    			if(err) return res.status(400).send(err);
    			//token을 원하는 곳(쿠키, 로컬스토리지 등. 여기서는 쿠키에 저장)에 저장한다. 
    			res.cookie("x_auth",user.token)
    				.status(200)
    				.json({loginSuccess:true,userId:user._id})
    			})
    		})

     

     

     

     

     

    최종 코드

    index.js

    const express = require('express');
    const app = express()
    const port = 8080
    //User model 가져오기
    const { User } = require("./models/User")
    //body-parser 가져오기
    const bodyParser = require('body-parser')
    //cookieparser 가져오기
    const cookieParser = require('cookie-parser');
    //body-parser 옵션주기 (Server에서 정보를 분석하여 가져올 수 있도록)
    app.use(bodyParser.urlencoded({extended: true})); //application/x-www-form-urlencoded
    app.use(bodyParser.json()); //application/json
    app.use(cookieParser()); //cookieparser 사용할 수 있음
    //key.js 가져오기
    const config = require('./config/key');
    //mongoose를 이용하여 어플리케이션과 mongo db 연결
    const mongoose = require('mongoose')
    mongoose.connect(config.mongoURI,{
        usenewurlparser: true, useUnifiedTopology: true
    }).then(()=>console.log('MongoDb Connected..'))
      .catch(err=>console.log(err))
    
    app.get('/',(req,res)=> res.send('Hello Hyojeong! nodemon 변경'))
    
    //회원가입을 위한 route만들기
    app.post('/api/users/register',(req,res) => {
        //Client에서 보내주는 정보들을 DB에 넣어주기
    
        const user = new User(req.body) //instance만들기 //req.body 안에는 bodyParser 덕분에 json 형식으로 data가 있다.
        user.save((err,userInfo)=>{
            if(err) return res.json({ success: false, err}) //성공하지 못했을 때 성공하지 못했다고 json 형식으로 전달되고 err message도 함께 전달한다.
            return res.status(200).json({ success: true })  //status(200) : 성공했다는 뜻
        })
    })
    
     app.post('/login',(req,res)=>{
         //요청된 이메일을 DB에 있는지 찾는다.
         User.findOne({email:req.body.email},(err,user)=>{
             if(!user){
                 return res.json({
                     loginSucces:false,
                     message:"제공된 이메일에 해당하는 user가 없습니다."
                 })
             }
             //요청된 이메일이 DB에 있다면 PWD가 맞는 PWD인지 확인
             user.comparePassword(req.body.password,(err,isMatch)=>{ //isMatch : db에 있는 pwd와 입력한 pwd가 일치
                 console.log('err',err)
                 if(!isMatch) //비밀번호가 틀렸을 경우
                 return res.json({loginSuccess: false, message:"비밀번호가 틀렸습니다."})
    
                 //비밀번호가 맞았을 경우. 토큰 생성
                 user.generateToken((err,user)=>{
                     if(err) return res.status(400).send(err); //err가 있을 때 clinet에 err전달
                    
                     //token을 원하는 곳(쿠키, 로컬스토리지 등. 여기서는 쿠키에 저장)에 저장한다. 
                     res.cookie("x_auth",user.token) //cookie Name에 x_auth 설정. cookie 내용에 user.token 설정.
                     .status(200)
                     .json({loginSuccess:true,userId:user._id})
                 })
             })
         })
    
    
     })
    
    app.listen(port, () => console.log(`Example app listening on port ${port}!`))

    user.js

    const mongoose = require('mongoose'); //mongoose module 가져오기
    const bcrypt = require('bcrypt')
    const saltRounds = 10 //10자리 salt
    const jwt = require('jsonwebtoken');
    const userSchema = mongoose.Schema({ //mongoose를 이용하여 schema 생성
        name:{
            type: String,
            maxlength: 50
        },
        email:{
            type: String,
            trim: true, //빈칸 제거
            unique: 1
        },
        password: {
            type: String,
            minlength: 5
        },
        role: {
            type: Number,
            default: 0
        },
        image: String,
        token:{
            type: String
        },
        tokenExp: {
            type: Number
        }
    })
    
    userSchema.pre('save',function(next){ //save: User 모델에 user 정보를 저장하기 전에 function을 실행한다.
        var user = this;
    
        if(user.isModified('password')){ //비밀번호가 변환될 때만 암호화하기
            //비밀번호를 암호화 시킨다.
            bcrypt.genSalt(saltRounds,function(err,salt){ //1.salt를 생성. (saltRounds가 필요함)
                if(err) return next(err) //err가 나면 index.js 에 user.save if(err)로 보낸다.
    
                bcrypt.hash(user.password,salt,function(err,hash){ //salt가 제대로 생성되었을 때. hash:암호화된 비밀번호
                    if(err) return next(err) //err
    
                    user.password=hash //hash를 만드는데 성공했다면 password를 hash로 교체하기
                    next()
                })
            })
        }else{
            next()
        }
        
        
    })
    
     userSchema.methods.comparePassword = function(plainPassword,cb){
         //plainPassword 1234567 암호화된 비밀번호:
         bcrypt.compare(plainPassword,this.password, function(err,isMatch){
             if(err) return cb(err);
             cb(null,isMatch)
         })
     }
    
     userSchema.methods.generateToken = function(cb){
         var user = this;
         //jsonwebtoken을 이용해서 token 생성
         var token = jwt.sign(user._id.toHexString(),'secretToken') //toHexString() : Return the ObjectID id as a 24byte hex string representation.
    
         // user._id + 'secretToken' = token
         // ->
        // 'secretToken' -> user._id
         
         user.token = token
         user.save(function(err,user){
             if(err) return cb(err)
             cb(null,user)
         })
     }
    const User = mongoose.model('User', userSchema) //model(model이름,schema)
    
    module.exports = { User } //model 을 다른 파일에서도 쓰기 위해 export하기

     

     

     

    /api/users/register
    /login

    성공적으로 로그인 됐다.

     

     

    참조 : https://www.youtube.com/watch?v=yWRj4GxFcr8

    728x90

    'node.JS' 카테고리의 다른 글

    [Node.js] AUTH 만들기  (0) 2022.01.01
    [node.js] bcrypt로 비밀번호 암호화하기  (0) 2021.12.31
    [Node.js] Nodemon 설치  (0) 2021.12.28
    [Node.js] 회원가입 기능 만들기  (0) 2021.12.28
    [Node.js] Mongoose schema 만들기  (0) 2021.12.28
Designed by Tistory.