카테고리 없음
Node.js | 로그인, 회원가입
JOOHUUN
2022. 8. 19. 21:07
$ npm init // package.json 파일 생성
$ npm install express --save
$ npm install mongoose --save // 몽고디비툴 설치
$ npm install nodemon --save-dev // node에서 liveserver 역할하는 툴
폴더 구조

1. package.json
{
"name": "youtube",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"backend": "nodemon index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.0.1",
"body-parser": "^1.20.0",
"cookie-parser": "^1.4.6",
"express": "^4.18.1",
"jsonwebtoken": "^8.5.1",
"mongoose": "^6.5.2"
},
"devDependencies": {
"nodemon": "^2.0.19"
}
}
2. index.js
- api 작성
const express = require('express');
const app = express();
const port = 5000;
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const config = require('./config/key');
const {User} = require("./models/User");
const mongoose = require('mongoose');
// application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: true}));
// application/json
app.use(bodyParser.json());
app.use(cookieParser());
// 몽고디비 연동
mongoose.connect(config.mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
}).then(() => console.log('MongDB Connected...!'))
.catch(err => console.log(err))
app.get('/', (req, res) => {
res.send('안녕하세요!!')
})
// 회원가입
app.post('/register', (req, res) => {
// req.body 안에는 json형식의 데이터가 들어 있음
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) => {
// 요청된 Email을 DB에 있는지 찾기
User.findOne({email: req.body.email}, (err, user) => {
if (!user) {
return res.json({loginSuccess: false,
message: "일치하는 유저가 없습니다."
});
}
// 요청된 이메일이 DB에 있다면 비밀번호가 일치한지 확인.
user.comparePassword(req.body.password, (err, isMatch) => {
if (!isMatch)
return res.json({loginSuccess: false,
message: "비밀번호가 틀렸습니다."
});
console.log(isMatch)
// 비밀번호 까지 맞다면 token 생성
user.generateToken((err, user) => {
if (err) return res.status(400).send(err);
// 토큰저장(로컬or쿠키)
res.cookie("x_auth", user.token)
.status(200)
.json({loginSuccess: true, userId: user._id});
});
});
});
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
// 몽고디비 연동
mongoose.connect(config.mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
}).then(() => console.log('MongDB Connected...!'))
.catch(err => console.log(err))
// config/dev.js
module.exports = {
mongoURI:'mongodb+srv://kimjuhoon:<password>@cluster0.4l2nw.mongodb.net/?retryWrites=true&w=majority'
}
mogoose에서 제공하는 connect함수를 사용해서 몽고디비와 연결
config.mongoURI는 config/dev.js 위치에 몽고디비키 입력
// 회원가입
app.post('/register', (req, res) => {
// req.body 안에는 json형식의 데이터가 들어 있음
const user = new User(req.body);
user.save((err) => {
if (err) return res.json({success: false, err});
return res.status(200).json({success: true});
});
});
const user = new User(req.body);
json형식의 데이터로 되어 있는 사용자가 요청한(reqeust) 값을 user라는 변수로 만듬
유효성 검증이 통과하지 못하면면 success: false, 그렇지 않으면 success: true
// 로그인
app.post('/login', (req, res) => {
// 요청된 Email을 DB에 있는지 찾기
User.findOne({email: req.body.email}, (err, user) => {
if (!user) {
return res.json({loginSuccess: false,
message: "일치하는 유저가 없습니다."
});
}
// 요청된 이메일이 DB에 있다면 비밀번호가 일치한지 확인.
user.comparePassword(req.body.password, (err, isMatch) => {
if (!isMatch)
return res.json({loginSuccess: false,
message: "비밀번호가 틀렸습니다."
});
console.log(isMatch)
// 비밀번호 까지 맞다면 token 생성
user.generateToken((err, user) => {
if (err) return res.status(400).send(err);
// 토큰저장(로컬or쿠키)
res.cookie("x_auth", user.token)
.status(200)
.json({loginSuccess: true, userId: user._id});
});
});
});
});
User.findOne({email: req.body.email}, (err, user) => {}
findeOne은 몽고디비에서 한개의 객체를 찾을 때 사용하는 함수이다
사용자가 요청한 email값이 디비에 있는지 확인 한 후 아래 코드 실행
비밀 번호가 일치 하는지 검사하는 comparePassword, 로그인 성공시 토큰을 생성하는 generateToken 함수는 User.js에서 작성하고 여기서는 간단한 로직만 작성한다.
3. User.js
- 모델 작성
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const saltRounds = 10;
const jwt = require('jsonwebtoken');
const userSchema = mongoose.Schema({
name: {
type: String,
maxlength: 50,
},
email: {
type: String,
trim: true,
unique: 1
},
password: {
type: String,
minlength: 3
},
lastname: {
type: String,
maxlength: 50
},
role: {
type: Number,
default: 0
},
image: String,
token: {
type: String,
},
tokenExp: {
type: Number
}
})
// 유저 모델의 유저정보를 저장하기 전에 실행함
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) {
var user = this;
// plainpassword = 해싱안된 암호
bcrypt.compare(plainPassword, user.password, function(err, isMatch) {
if (err) return cb(err, isMatch);
cb(null, isMatch);
});
};
userSchema.methods.generateToken = function (cb) {
var user = this;
// jsonwebtoken 이용하여 토큰 생성
// user._id + 'secretToken' = token
// 'secretToken'을 디코딩하면 user._id
var token = jwt.sign(user._id.toHexString(), "secretToken");
user.token = token;
user.save(function (err, user) {
if (err) return cb(err);
cb(null, user);
});
};
const User = mongoose.model('User', userSchema);
module.exports = {User};