암호화
암호화되는 작업을 하기 위해서 모듈이 필요하다
npm install crypto --save 암호화 모듈을 설치한다
crypto 모듈은 사용자가 pwd를 입력하면 그 pwd에다가 salt라는 키를 붙여서 암호화 한다
Express 기본 모듈
//Express 기본 모듈
require("dotenv").config();
var express = require("express");
var http = require("http");
var path = require("path");
var serveStatic = require("serve-static");
var expressErrorHandler = require("express-error-handler");
var expressSession = require("express-session");
var mongoose = require("mongoose");
crypto(암호화)모듈
var crypto = require("crypto")
var database;
var UserSchema;
var UserModel;
몽고디비 데이터베이스 연결
//데이터베이스 연결
function connectDB(){
//데이터베이스 연결 정보
var databaseUrl = "mongodb://localhost:27017/shopping";
//연결
mongoose.connect(databaseUrl);
database = mongoose.connection;
database.on("open",function(){
// 스키마 모델 객체
createUserSchema(); // 함수로 호출할것임
});
database.on("error",console.error.bind(console,"몽구스 연결 에러..."));
database.on("disconnected",function(){
console.log("DB연결이 끊겼습니다 5초후 재연결 합니다");
setInterval(connectDB(),5000);
});
}
스키마 정의 한것을 함수로 뺼것임 그 사이에 Virtual를 넣으면 함수가 길어지므로
function createUserSchema(){
UserSchema = mongoose.Schema({
id:{type:String,required:true,unique:true}, // 아이디에 들어가는 값은 문자고 required 반드시 필요하고 , 유의값 - > 프라이머리키가 됨
hashed_password:{type:String,required:true}, // 암호화된 패스워드 이다. 그러므로 hashed_pwd로 바꿈
// 암호화 + salt , salt키를 저장해야함 안하면 High문자를 저장하면 a123를 넣으면 high라는애를 가지고 와서 붙여서 암호화를 해야하는데 암호화된게 hashed_pwd로 들어가는데
salt:{type:String,required:true},// 다음에도 123를 붙이는데 앞에 salt키가 있어야되므로 항상 보관되어 있어야 한다. 암호화시킬때 임의로 붙이는 키값이다 . 반드시 필요하므로 required : true
name:{type:String},
age:{type:Number,'default':20},
created:{type:Date,index:{unique:false},'default':Date.now} // unique:false 똑같은값이 들어가도 상관없다 , 날짜를 안넣으면 오늘날짜
});
UserSchema
.virtual("pwd") // 암호는 뭘로 만들건가 password로 만듬 , password값으로 넣겠다
.set(function(pwd){
this._password = pwd; // 패스워드를 넣을것이다. _password 외부변수이다. 바꾸면 안됨
this.salt = this.makeSalt(); // 아래에서 만든 salt키값을 _salt에 넣을것이다.
this.hashed_password = this.encryptPassword(pwd); // 암호화를 시키는 메소드이다 밑에 만들것임
})
.get(function(){
return this._password; // 패스워드 반환값 이 값을 hashed_password:{type:String,required:true} 에 넣는다
})
스키마 객체에 메소드를 추가 : method() 방법
UserSchema.method("makeSalt",function(){ // 메소드를 만들면서 makeSalt를 호출함
// return "hi"; // hi붙이고싶다 hi라는 문자가 this.makeSalt()에서 호출되는데 salt에 hi가 들어감
// db에 salt:{type:String,required:true} 들어감
// hi 123 A , hi 456 B , hi 787 C
// 암호화할때 hi만 붙이게되면 패스워드를 암호화하는 방식이 너무 단순
// A라는 사람이 로그인할때 hi라고 하지않고 abc123
// B라는 사람이 접속하면 123456
// c라는 사람이 접속하면 265189
// 그 사람만의 고유 salt를 만드는 것이다.
// id pw salt
// A 123 abc = XXX 암호화된 결과물
// B 456 129
// C 789 369
// 즉 독자적인 salt키를 갖게 된다.
// pw + salt 를 암호화된 pwd와 비교하게 된다 .
// 실제패스워드를 저장하지않고 암호화된 패스워드 저장함
// 각자의 salt키도 저장해야 한다.
// 지금은 시시각각 변하는 난수값을 넣어서 알아내기 쉽지 않다
console.log("date : " + new Date().valueOf()); // 초에따라 일련숫자 12341242 나옴
console.log("math : " + Math.random()); // 0.1234214242 매번바뀜
return Math.round((new Date().valueOf() * Math.random())) + ""; // 랜덤함수를 그순간에 만들어서 뒤에 + 붙여서 문자가됨 그러면 패스워드랑 붙을수있다. String값이됨
})
★ 암호화 작업을 하는 곳
UserSchema.method("encryptPassword",function(inputPwd,inSalt){ // 암호화를 시키려면 입력되는 패스워드 inputPwd 를 넣음
// 암호화 하려면 salt가 필요하므로 inSalt
// 그러면 들어가는 패스워드와 salt 가 합쳐져서 암호화가 된다.
// 이미 암호화가 되어있으면 로그인이 되어있으면 123 입력하면
// 얘를 암호화 해서 기존에 저장되어있는 암호화된 데이터를 같냐 해서 비교작업을 해줘야 하다.
if(inSalt) { // inSalt가 있으면
// 암호화 작업
return crypto.createHmac("sha1",inSalt) // sha1 암호화 용어인데 쉬바라고 읽는다. 1은 암호화하는 등급이다. 암호화하는 모듈로써 모든곳에서 다쓴다
.update(inputPwd).digest("hex"); // hex 헥사라고 읽음
} else {
// 안주게 되면 this 자체적으로 salt키를가지고 있으면 그걸써라
return crypto.createHmac("sha1",this.salt) // sha1 암호화 용어인데 쉬바라고 읽는다. 1은 암호화하는 등급이다. 암호화하는 모듈로써 모든곳에서 다쓴다
.update(inputPwd).digest("hex");
}
})
123를 암호화해서 암호화된 데이터를 비교해야되는 메소드를 만들어야한다.
로그인할때 암호화된 PWD비교
UserSchema.method("authenticate",function(inputPwd,inSalt,hashed_password){ // 사용자가 입력할 패스워드가 필요
// inputPwd + insalt 가 들어오면 123high 해서 암호화한다.
// 암호화된 데이터가 db에 저장되어있는 암호화된 데이터를 읽어내야 한다
// 두개를 비교하는데 inputPwd , insalt 와 db에서 꺼내온 암호화된 패스워드 hashed_password가 필요하다
if(inSalt) { // 설트키 가 있으면
console.log("사용자 입력 pwd: " + inputPwd); // abc
console.log("암호화된 pwd: " + this.encryptPassword(inputPwd,inSalt)); // 암호화된 패스워드를 보여줄것이다. abc가 xxxxxxx
console.log("DB에 저장되어 있는 pwd: " + hashed_password);// db에 저장되어있는 암호화된 패스워드 abc가 db에저장된 암호화된 데이터
// a 123 + salt 와 db에서 읽어온것과 일치하면 true 반환
return this.encryptPassword(inputPwd,inSalt)==hashed_password; // 암호화된 시킨것과 db에 저장된것과 일치하나? true , false
} else { // 설트키 가 없으면 패스워드만 감
// 위에서 부르면 function 에 inSalt가 없으면 this.Salt 로 감
console.log("사용자 입력 pwd: " + inputPwd); // abc
console.log("암호화된 pwd: " + this.encryptPassword(inputPwd,inSalt)); // 암호화된 패스워드를 보여줄것이다. abc가 xxxxxxx
console.log("DB에 저장되어 있는 pwd: " + hashed_password);// db에 저장되어있는 암호화된 패스워드 abc가 db에저장된 암호화된 데이터
return this.encryptPassword(inputPwd)==this.hashed_password;
}
});
스키마 객체에 메소드를 추가(방법: static(), method() )
로그인에서 사용
findById는 메소드의 이름 뒤에 콜백함수
static를 써서 메소드
UserSchema.static("findById",function(id,callback){ // 아이디를 가지고 select 했을때 들어갔을때 무조건 작업이 끝났을때 결과가 콜백으로 간다.
return this.find({id:id},callback); // id를 찾아라 찾던안찾던 callback함수 실행해라
})
// 전체 데이터 사용
UserSchema.static("findAll",function(callback){ // findAll 메소드를
return this.find({}, callback); // 전체데이터는 조건이 없어서 {} 몽땅가져옴
})
console.log("UserSchema 정의함.");
//Model 정의
// users2 새로운 컬렉션(테이블)이 만들어지면서 위의 5개의 데이터를 저장하게 된다.
UserModel = mongoose.model("users3",UserSchema); // UserSchema 에 findByid , findAll 이 들어왔으니까 userModel.findByid , userModel.findAll 로 찾을수있다.
console.log("UserModel 정의함.");
}
익스프레스 객체 생성
var app = express();
app.set("port",process.env.PORT||3000);
app.use(express.urlencoded({extended:false}));
app.use("/public",serveStatic(path.join(__dirname,"public")));
app.use(expressSession({
secret:"my key",
resave:true,
saveUninitialized:true
}));
사용자를 인증하는 함수
var authUser = function(database,id,pwd,callback){
console.log("authUser 함수 호출..");
//아이디와 비밀번호 검색
//id가 function(id,callback) 에서 find({id:id}로 찾아 오게되면서 결과가 callback함수가 에러면 err 잘나오면result 로 들어감
// 즉 , 콜백함수는 id를 찾았을경우 실행된결과를 받음
UserModel.findById(id, function(err,result){ // 아이디 패스워드 체크했었는데 이젠 id만 주면됨
// 에러가 있으면 이걸 실행
if(err){
callback(err,null);
return;
}
//데이터가 있을경우
if(result.length>0){
console.log("아이디와 일치하는 사용자 찾음")
// 무조건 배열로 넘어옴
// ._doc = 도큐먼트 DB 값을 비교
// 암호화된 데이터 비교
var user = new UserModel({id:id});
var authenticated =
user.authenticate(pwd,result[0]._doc.salt,result[0]._doc.hashed_password); // 위에 메소드 UserSchema.method("authenticate",function(inputPwd,inSalt,hashed_password) 호출
// pwd , salt키 = db암호화된 비교작업
// authenticated 에는 true 아니면 fasle 가 들어가게됨
} if(authenticated){ // 사용자가 입력한 pwd가 일치하나 ?
console.log("비밀번호 일치함")
callback(null,result); // 에러는 없으니 null ,데이터 있으니 result 는 넣어줌
} else {
console.log("비밀번호가 일치하지 않음");
callback(null,null); // 에러없고 결과가 없으니 null , null
}
/*} else {
console.log("아이디와 일치하는 데이터가 없습니다.");
callback(null,null); // 에러없고 결과가 없으니 null , null
}*/
});
}
사용자를 추가하는 함수
var addUser = function(database,id,pwd,name,callback){
console.log("addUser 함수 호출..");
var users = new UserModel({"id":id, "pwd":pwd, "name":name});
users.save(function(err,result){
if(err){
callback(err,null);
return;
}
if(result){
console.log("사용자 추가..");
}else{
console.log("사용자 추가 실패..");
}
callback(null,result);
});
};
// 라우터 객체 생성
var router = express.Router();
// 로그인 라우터
router.route("/process/login").post(function(req,res){
console.log("/process/login 호출..");
var id = req.body.id;
var pwd = req.body.pwd;
if(database){
authUser(database, id, pwd, function(err,result){
if(err) {throw err;}
if(result){
var userName = result[0].name;
res.writeHead("200",{"Content-type":"text/html;charset=utf-8"});
res.write("<h1>로그인 성공</h1>")
res.write("<div>아이디: " + id + "</div>");
res.write("<div>이름: " + userName + "</div>");
res.write("<br/><br/><a href='/public/login.html'>다시 로그인</a>");
res.end();
}else{
res.writeHead("200",{"Content-type":"text/html;charset=utf-8"});
res.write("<h1>로그인 실패</h1>")
res.write("<div>아이디 또는 패스워드를 확인하세요</div>");
res.write("<br/><br/><a href='/public/login.html'>다시 로그인</a>");
res.end();
}
});
}else{
res.writeHead("200",{"Content-type":"text/html;charset=utf-8"});
res.write("<h1>데이터베이스 연결 실패</h1>")
res.write("<div>데이터베이스를 연결하지 못했습니다.</div>");
res.end();
}
});
사용자 추가 라우터
router.route("/process/addUser").post(function(req,res){
console.log("/process/addUser 호출..");
var id = req.body.id;
var pwd = req.body.pwd;
var name = req.body.name;
if(database){
addUser(database, id, pwd, name, function(err,result){
if(err) {throw err;}
if(result){
res.writeHead("200",{"Content-type":"text/html;charset=utf-8"});
res.write("<h1>사용자 추가 성공</h1>")
res.end();
}else{
res.writeHead("200",{"Content-type":"text/html;charset=utf-8"});
res.write("<h1>사용자 추가 실패</h1>")
res.end();
}
});
}else{
res.writeHead("200",{"Content-type":"text/html;charset=utf-8"});
res.write("<h1>데이터베이스 연결 실패</h1>")
res.write("<div>데이터베이스를 연결하지 못했습니다.</div>");
res.end();
}
});
사용자 리스트 라우터
폼버튼을 눌렀을때의 주소임
router.route("/process/listUser").post(function(req,res){
console.log("/process/listUser 호출됨")
// db에서 데이터 가져옴
if(database) { // 데이터베이스 객체가 있으면 연결해서 데이터 가져옴
/*UserSchema.static("findAll",function(callback){
return this.find({}, callback);
})*/
// 함수 호출하면됨
UserModel.findAll(function(err,result){ // 모든데이터 가져오는 메소드 static("findAll", -> find{} 넘겨주는값이 필요없음 function(err,result) 로 처리
if(err) { // 에러가 발생하면
res.writeHead("200",{"Content-type":"text/html;charset=utf-8"});
res.write("<h2>사용자 리스트 조회중 에러 발생</h2>")
res.end();
return; // 밑에 실행하지 않게 return 꼭 써줌
}
if(result){ // 정상적으로 데이터를 가지고 왔을때
// 모양 디자인 만드는 것임
res.writeHead("200",{"Content-type":"text/html;charset=utf-8"});
res.write("<h2>사용자 리스트</h2>")
res.write("<div><ul>");
for(var i=0; i<result.length; i++) {
var id = result[i]._doc.id; // 여러개니까 i번째
var name = result[i]._doc.name;
var age = result[i]._doc.age;
// ul안에 들어가있으니 li , number니까 # 하나 붙이고 i+1은 일련번호 , : 구분자 해주고 엔터치고 id + , + name + , + age + <li>
res.write('<li>#'+ (i+1) + ' : '
+ id + ", " + name + ' , ' + age + '</li>' )
}
res.write("</ul></div>");
res.write("<br/><br/><a href='/public/listUser.html'>리스트</a>");
res.end()
} else {
// 데이터가 없을 경우
res.writeHead("200",{"Content-type":"text/html;charset=utf-8"});
res.write("<h2>사용자 조회 실패</h2>")
res.end();
}
})
}
});
라우터 객체 등록
app.use("/",router);
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"));
//DB연결 함수 호출
connectDB();
});
'JAVA Programming > JDBC' 카테고리의 다른 글
[하루 계획]2022-04-07 (0) | 2022.04.07 |
---|---|
[javascript] 모듈 분리 3가지 방법 (0) | 2022.04.07 |
[Node.js] mongoose 데이터베이스 연결 (0) | 2022.04.07 |
[Node.js] mongoose 모듈 (0) | 2022.04.06 |
[하루 계획]2022-04-06 (0) | 2022.04.06 |