반응형
require 요소들
//익스프레스로 웹 서버 만들기
// Express 기본 오듈 불러오기
var express = require('express'),
http = require('http'),
path = require('path');
var bodyParser = require('body-parser'),
cookieParser = require('cookie-parser'),
errorHandler = require('errorhandler');
var expressErrorHandler = require('express-error-handler');
var expressSession = require('express-session');
var static = require('serve-static');
var crypto = require('crypto');
var user = require('./routes/user')
//익스프래스 객체 생성
var app = express();
기본 설정
//기본 포트를 app 객체에 속성으로 설정
app.set('port', process.env.PORT || 3000);
//body-parser를 사용해 application/x-www-form-urlencoded 파싱
app.use(bodyParser.urlencoded({ extended: false }));
//body-parser를 사용해 application/json 파싱
app.use(bodyParser.json());
app.use(express.static(__dirname + '/public'));
//app.use('/public', static(path.join(__dirname, 'public')));
//cookie-parser 설정
app.use(cookieParser());
app.use(expressSession({
secret: 'my key',
resave: true,
saveUnintialized: true
}));
MongoDB 연결 및 변수 선언
var MongoClient = require('mongodb').MongoClient;
var mongoose = require('mongoose');
var database;
var UserSchema;
var UserModel
// MongoDB 연결 함수
function connectDB() {
//데이터베이스 연결 정보
var databaseUrl = 'mongodb://localhost:27017/local';
console.log("데이터 베이스 연결을 시도합니다.");
mongoose.Promise = global.Promise;
mongoose.connect(databaseUrl);
database = mongoose.connection;
database.on('err',console.error.bind(console, 'mongoose connection error'));
database.on('open', function(){
console.log('데이터 베이스에 연결 되었습니다. ' + databaseUrl);
//user 스키마 및 모델 객체 생성
createUserSchema();
});
//연결이 뜮어졌을 때 5초후 재연결
database.on('disconnected', function(){
console.log('연결이 끊어졌습니다. 5초 후 다시 연결합니다.');
setInterval(connectDB, 5000);
})
}
createUserSchema 함수
function createUserSchema() {
UserSchema = require('./database/user_schema').createSchema(mongoose);
UserModel = mongoose.model("users", UserSchema);
console.log("UserModel 정의함");
user.init(database,UserSchema,UserModel)
}
./database/user_schema 파일
var crypto = require('crypto');
var schema = {};
// 스키마를 생성 및 설정하는 함수
schema.createSchema = function (mongoose) {
//스키마 정의
//password를 hashed_password로 변경, default 속성 모두 추가, salt 속성 추가
var UserSchema = mongoose.Schema({
id : {type : String, required : true, unique : true, 'default' : ' '},
hashed_password : {type : String, required : true, unique : true, 'default' : ' '},
salt : {type : String, required: true},
name : {type : String, ondex : 'hashed', default : ' '},
created_at : {type : Date, index : {unique : false}, 'default' : Date.now},
updated_at : {type : Date, index : {unique : false}, 'default' : Date.now}
});
//password를 virtual 메소드로 정의 : MongoDB 에 저장되지 않는 편리한 속성임, 특정 속성을 지정하고 set, get 메소드를 정의함
UserSchema
.virtual('password')
.set(function(password) {
this._password = password;
this.salt = this.makeSalt();
this.hashed_password = this.encryptPassword(password);
console.log('virtual password 호출됨' + this.hashed_password);
})
.get(function() {return this._password});
//스키마에 모델 인스턴스에서 사용할 수 있는 메소드 추가
//비밀번호 암호화 메소드
UserSchema.method('encryptPassword',function(plainText,inSalt) {
if(inSalt) {
return crypto.createHmac('sha1', inSalt).update(plainText).digest('hex');
}
else {
return crypto.createHmac('sha1', this.salt).update(plainText).digest('hex');
}
});
//salt 값 만들기 메소드
UserSchema.method('makeSalt', function() {
return Math.round((new Date().valueOf() * Math.random())) + '';
});
//인증 메소드 - 입력된 비밀번호와 비교 (true/false 반환)
UserSchema.method('authenticate', function(plainText, inSalt, hashed_password) {
if(inSalt) {
console.log('authenticate 호출됨 : %s -> %s : %s', plainText,
this.encryptPassword(plainText, inSalt), hashed_password);
return this.encryptPassword(plainText, inSalt) == hashed_password;
}
else {
console.log('authenticate 호출됨 : %s -> %s : %s', plainText,
this.encryptPassword(plainText), hashed_password);
return this.encryptPassword(plainText) == hashed_password;
}
});
//필수 속성에 대한 유효성 확인 (길이 값 체크)
UserSchema.path('id').validate(function(id) {
return id.length;
}, 'id 칼럼의 값이 없습니다.');
UserSchema.path('name').validate(function(name) {
return name.length;
}, 'name 칼럼의 값이 없습니다.');
// 스키마에 static 메소드 추가
UserSchema.static('findById', function(id, callback) {
return this.find({id : id},callback);
});
UserSchema.static('findAll',function(callback) {
return this.find({ }, callback);
})
console.log("스키마 정의함");
return UserSchema;
}
module.exports = schema;
라우터 및 서버 연결
//라우터 객체 참조
var router = express.Router();
router.route('/process/login').post(user.login);
router.route('/process/adduser').post(user.adduser);
app.use('/' , router );
//=====404 오류 페이지 처리========//
var errorHandler = expressErrorHandler({
static: {
'404' : './public/404.html'
}
});
app.use(expressErrorHandler.httpError(404));
app.use(errorHandler);
//Express 서버 시작
http.createServer(app).listen(app.get('port'), function () {
console.log('웹 서버가 시작되었습니다. : ' + app.get('port'));
//데이터 베이스 연결
connectDB();
});
./router/user 파일
var database;
var UserSchema;
var UserModel;
var init = function(db, schema, model) {
console.log('init 호출됨');
database = db;
UserSchema = schema;
UserModel = model;
}
var login = function(req,res) {
console.log('user 모듈안에 있는 login 호출됨');
var paramId = req.params.id || req.body.id || req.query.id;
var paramPassword = req.params.password || req.body.password || req.query.password;
if(database) {
authUser(database, paramId, paramPassword, function(err, docs) {
if(err) {throw err;}
if(docs) {
console.dir(docs);
var username = docs[0].name;
res.writeHead(200,{'Content-Type':'text/html; charset=utf8'});
res.write('<h1>로그인 성공</h1>');
res.write('<div><p>사용자 아이디 : ' + paramId + '</p></div>');
res.write('<div><p>사용자 비밀번호 : ' + paramPassword + '</p></div>');
res.write("<br><br><a href='/'>다시 로그인하기</a>");
res.end();
} else {
res.writeHead(200,{'Content-Type':'text/html; charset=utf8'});
res.write('<h1>로그인 실패</h1>');
res.write('<div><p>아이디와 비밀번호를 다시 확인하십시오.</p></div>');
res.write("<br><br><a href='/'>다시 로그인하기</a>");
res.end();
}
});
} else {
res.writeHead(200,{'Content-Type':'text/html; charset=utf8'});
res.write('<h1>데이터 베이스 연결 실패</h1>');
res.write('<div><p>데이터 베이스에 연결하지 못했습니다.</p></div>');
res.end();
}
}
var adduser = function(req, res) {
console.log('user 모듈안에 있는 adduser 호출됨');
var paramId = req.body.id || req.query.id;
var paramPassword = req.body.password || req.query.password;
var paramName = req.body.name || req.query.name;
console.log('요청 파라미터 : ' + paramId + ', ' + paramPassword + ', ' + paramName);
// 데이터 베이스 객체가 초기화된 경우, addUser 함수 호출하여 사용자 추가
if(database) {
addUser(database, paramId, paramPassword, paramName, function(err, result) {
if(err) {throw err;}
if(result && result.insertedCount > 0) {
console.dir(result);
res.writeHead(200,{'Content-Type':'text/html; charset=utf8'});
res.write('<h2>사용자 추가 성공</h2>');
res.end();
} else {
res.writeHead(200,{'Content-Type':'text/html; charset=utf8'});
res.write('<h2>사용자 추가 실패</h2>');
res.end();
}
});
} else {
res.writeHead(200,{'Content-Type':'text/html; charset=utf8'});
res.write('<h2>데이터베이스 연결 실패</h2>');
res.end();
}
}
// 사용자를 인증하는 함수 : 아이디로 먼저 찾고 비밀번호를 그 다음에 비교
var authUser = function(database, id, password, callback) {
console.log('authUser 호출됨 : ' + id + ', ' + password);
//1. 아이디를 사용해 검색
UserModel.findById(id, function(err, results) {
if(err) {
callback(err,null);
return;
}
console.log('아이디 [%s]로 사용자 검색 결과', id);
console.dir(results);
if(results.length > 0) {
console.log('아이디와 일치하는 사용자 찾음');
//2. 비밀번호 확인 : 모델 인스턴스 객체를 만들고 authenticate() 메소드 호출
var user= new UserModel({id : id});
var authenticated = user.authenticate(password,results[0]._doc.salt,
results[0]._doc.hashed_password);
if(authenticated) {
console.log('비밀번호 일치함');
callback(null,results);
}
else {
console.log('비밀번호 일치하지 않음')
callback(null,null);
}
}
});
}
var addUser = function(database, id, password, name, callback) {
console.log('addUser 호출됨 : ' + id + ', ' + password + ', ' + name);
//UserModel 인스턴스 생성
var user = new UserModel({"id" : id, "password" : password, "name" : name});
//save()로 저장
user.save(function(err) {
if(err) {
callback(err,null);
return;
}
console.log("사용자 데이터 추가함.");
callback(null,user);
});
//users 컬렉션 참조
var users = database.collection('users');
//id, password, username을 사용해 사용자 추가
users.insertMany([{"id":id, "password":password, "name":name}], function(err, result) {
if(err) {
callback(err,null);
return;
}
// 오류가 아닌 경우, 콜백함수를 호출하면서 결과 객체 전달
if(result.insertedCount > 0) {
console.log("사용자 레코드 추가됨 : " + result.insertedCount);
} else {
console.log("추가된 레코드가 없음.")
}
callback(null, result);
})
}
module.exports.init = init;
module.exports.login = login;
module.exports.adduser = adduser;
전체 페이지 창
728x90
반응형
'Back End > Node.js' 카테고리의 다른 글
[Node.js] 구름 ide에서 MongoDB 사용하기 (1) | 2020.10.03 |
---|---|
[Node.js] 파일 읽고 쓰기 (동기화/ 비동기화) (0) | 2020.08.15 |
[Node.js] 간단한 웹 서버 만들기 (0) | 2020.08.15 |