d-_-s 2023. 2. 19. 10:41

User.js의 userSchema.pre에서 비밀번호 변경 외의 다른 작업을 진행할 시 그다음단계로 진행시키기 위해 else문을 추가한다.

 

// mongoose를 요청함
const mongoose = require('mongoose');

// bcrypt를 요청
const bcrypt = require('bcrypt');

// Salt를 이용해서 비밀번호를 암호화 해야하기 때문에 saltRounds를 설정
const saltRounds = 10

// Schema 설정
const userSchema = mongoose.Schema({
    name: {
        type: String,
        maxlength: 50
    },
    email: {
        type: String,
        trim: true,
        unique: 1
    },
    password: {
        type: String,
        minlength: 5
    },
    lastname: {
        type: String,
        maxlength: 50
    },
    role: {
        type: Number,
        default: 0
    },
    image: String,
    token: {
        type: String
    },
    tokenExp: {
        type: Number
    }
})

// user 정보를 저장하기전에 비밀번호를 암호화시킨다.
userSchema.pre('save', function (next) {
    // userSchema를 가져옴
    var user = this;

    // 비밀번호를 바꿀때만 암호화한다.
    if (user.isModified('password')) {

        // 비밀번호를 암호화 시킨다.
        bcrypt.genSalt(saltRounds, function (err, salt) {
            if (err) return next(err)

            bcrypt.hash(user.password, salt, function (err, hash) {
                if (err) return next(err)
                user.password = hash
                next()
            })
        })
    }
    else{
        next()
    }
})


// Schema를 모듈로 감싸 줌
const User = mongoose.model('User', userSchema)

// 모듈을 다른 곳에서도 사용할 수 있도록 하는 코드
module.exports = { User }

 

로그인 기능 구현

로그인 기능을 구현하기 위해 index.js에 아래의 코드를 추가한다.

아래의 코드는 데이터베이스에서 요청된 이메일을 찾고 데이터베이스에 요청된 이메일이 있다면 비밀번호가 맞는지 확인하는 코드이다.

app.post('/login', (req, res) => {
    User.findOne({ email: req.body.email }, (err, user) => {

        // 요청된 이메일을 데이터베이스에서 있는지 찾는다.
        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 req.json({loginSuccess: false, message: "비밀번호가 틀렸습니다."})

            // 비밀번호 까지 맞다면 토큰을 생성하기.
            user.generateToken((err, user) => {

            })
            
        })
    })
})

index.js

// express 모듈을 추가
const express = require('express')
// 새로운 express 모듈을 생성
const app = express()
// port 설정
const port = 5000
// User 모델을 가져옴
const { User } = require("./models/User");
// bodyPaser를 가져옴
const bodyPaser = require("body-parser");
// config를 가져옴
const config = require('./config/key');

// bodyPaser 옵션주기
// application/s-www-form-urlencoded
app.use(bodyPaser.urlencoded({ extended: true }));
// application/json
app.use(bodyPaser.json());

// mongoose 연결
const mongoose = require('mongoose')
// error 발생을 막기 위한 코드
mongoose.connect("mongodb+srv://<아이디>:<비밀번호>@boilerplate.6t2ootw.mongodb.net/?retryWrites=true&w=majority"
).then(() => console.log('MongoDB Connected...'))      // DB 연결 확인을 위한 코드
    .catch(err => console.log(err))

// Hello World! 전송
app.get('/', (req, res) => {
    res.send('Hello World!!')
})

app.post('/register', (req, res) => {

    // 회원 가입 할때 필요한 정보들을 client에서 가져오면 그것들을 데이터 베이스에 넣어준다.

    const user = new User(req.body)

    user.save((err, userInfo) => {
        if (err) return res.json({ success: false, err })
        return res.status(200).json({
            success: true
        })
    })
})

app.post('/login', (req, res) => {
    User.findOne({ email: req.body.email }, (err, user) => {

        // 요청된 이메일을 데이터베이스에서 있는지 찾는다.
        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 req.json({loginSuccess: false, message: "비밀번호가 틀렸습니다."})

            // 비밀번호 까지 맞다면 토큰을 생성하기.
            user.generateToken((err, user) => {

            })
            
        })
    })
})

// 5000번 port에서 실행
app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

 

비밀번호 확인을 위하여 User.js에 userSchema.methods.comparePassword 함수를 구현한다.

 

User.js

// mongoose를 요청함
const mongoose = require('mongoose');

// bcrypt를 요청
const bcrypt = require('bcrypt');

// Salt를 이용해서 비밀번호를 암호화 해야하기 때문에 saltRounds를 설정
const saltRounds = 10

// Schema 설정
const userSchema = mongoose.Schema({
    name: {
        type: String,
        maxlength: 50
    },
    email: {
        type: String,
        trim: true,
        unique: 1
    },
    password: {
        type: String,
        minlength: 5
    },
    lastname: {
        type: String,
        maxlength: 50
    },
    role: {
        type: Number,
        default: 0
    },
    image: String,
    token: {
        type: String
    },
    tokenExp: {
        type: Number
    }
})

// user 정보를 저장하기전에 비밀번호를 암호화시킨다.
userSchema.pre('save', function (next) {
    // userSchema를 가져옴
    var user = this;

    // 비밀번호를 바꿀때만 암호화한다.
    if (user.isModified('password')) {

        // 비밀번호를 암호화 시킨다.
        bcrypt.genSalt(saltRounds, function (err, salt) {
            if (err) return next(err)

            bcrypt.hash(user.password, salt, function (err, hash) {
                if (err) return next(err)
                user.password = hash
                next()
            })
        })
    }
    else {
        next()
    }
})

// 비밀번호가 맞는지 확인하는 함수
userSchema.methods.comparePassword = function (plainPassword, cb) {

    // plainPassword : 입력하는 비밀번호
    // 암호화된 비밀번호 : DB에 있는 비밀번호

    bcrypt.compare(plainPassword, this.password, function (err, isMatch) {
        if (err) return cb(err),
            cb(null, isMatch)
    })
}



// Schema를 모듈로 감싸 줌
const User = mongoose.model('User', userSchema)

// 모듈을 다른 곳에서도 사용할 수 있도록 하는 코드
module.exports = { User }