UserModel은 Schema를 감싸 주는 역할을 한다
Schema는 데이터베이스를 구성하는 데이터 개체, 속성, 관계 및 데이터조작 시 데이터 값들이 갖는 제약 조건 등에 대해 전반적으로 정의한다.
const userSchema = mongoose.Schema({
name: {
type: String,
maxlength: 50
},
email: {
type: String,
trim: true,
unique: 1
},
password: {
type: String,
minglength: 5
},
lastname: {
type: String,
maxlength: 50
},
role: {
type: Number,
default: 0
},
image: String,
token: {
type: String,
},
tokenExp: {
type: Number
}
})
(사진 출처: http://pismute.github.io/whygitisbetter/images/local-remote.png)
Repository : 저장소를 의미하며, 저장소는 히스토리, 태그, 소스의 가지치기 혹은 branch에 따라 버전을 저장한다. 저장소를 통해 작업자가 변경한 모든 히스토리를 확인 할 수 있다.
Working Tree : 작업자의 현재 시점.
Staging Area : 저장소에 커밋하기 전에 커밋을 준비하는 위치.
Commit : 현재 변경된 작업 상태를 점검을 마치면 확정하고 저장소에 저장하는 작업.
Head : 현재 작업중인 Branch
Branch : 가지 또는 분기점을 의미하며, 작업을 할때에 현재 상태를 복사하여 Branch에서 작업을 한 후에 완전하다 싶을때 Merge를 하여 작업을 한다.
Merge : 다른 Branch의 내용을 현재 Branch로 가져와 합치는 작업을 의미한다.
단방향 암호화를 위해 만들어진 Hash 함수
기존 해쉬 함수들은 rainbow table attack(미리 Hash값들으 계산해놓은 테이블로 원래 정보를 찾아내는 해킹방법)에 취약함
https://www.npmjs.com/package/bcrypt
NPM 공식 사이트에서 Install 및 usage 방법을 숙지, 프로젝트에 적용
userSchema.pre('save', function (next) {
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()
}
});
user모델에서 user정보를 받아온뒤 password를 hash함수로 암호화
userSchema.methods.comparePassword = function (plainPassword, cb) {
bcrypt.compare(plainPassword, this.password, function (err, isMatch) {
if (err) return cb(err);
cb(null, isMatch)
})
}
로그인 시 비밀번호를 check한뒤 일치하면 null값을 리턴하도록 callback함수로 지정한다
전자 서명 된 URL-safe (URL로 이용할 수있는 문자 만 구성된)의 JSON으로
전자 서명은 JSON 의 변조를 체크 할 수 있게되어 있다
JWT는 서버와 클라이언트 간 정보를 주고 받을 때 Http 리퀘스트 헤더에 JSON 토큰을 넣은 후 서버는 별도의 인증 과정없이 헤더에 포함되어 있는 JWT 정보를 통해 인증
https://www.npmjs.com/package/jsonwebtoken
npm 공식 페이지에서 나온대로 사용한다. 본 프로젝트에서는
userSchema.methods.generateToken = function (cb) {
var user = this;
console.log('user', user)
console.log('userSchema', userSchema)
var token = jwt.sign(user._id.toHexString(), 'secret')
var oneHour = moment().add(1, 'hour').valueOf();
user.tokenExp = oneHour;
user.token = token;
user.save(function (err, user) {
if (err) return cb(err)
cb(null, user);
})
}
로 토큰을 만든뒤에 user Schema에서 토큰 필드에 저장을 한다.
const userSchema = mongoose.Schema({
name: {
type: String,
maxlength: 50
},
email: {
type: String,
trim: true,
unique: 1
},
password: {
type: String,
minglength: 5
},
lastname: {
type: String,
maxlength: 50
},
role: {
type: Number,
default: 0
},
image: String,
token: {
type: String,
},
tokenExp: {
type: Number
}
})
저장된 토큰필드에서 토큰을 비교하여 쿠키에 저장된 토큰과 동일하면 loginSuccess:True를 반환
router.post("/login", (req, res) => {
User.findOne({ email: req.body.email }, (err, user) => {
if (!user)
return res.json({
loginSuccess: false,
message: "Auth failed, email not found"
});
user.comparePassword(req.body.password, (err, isMatch) => {
if (!isMatch)
return res.json({ loginSuccess: false, message: "Wrong password" });
user.generateToken((err, user) => {
if (err) return res.status(400).send(err);
res.cookie("w_authExp", user.tokenExp);
res
.cookie("w_auth", user.token)
.status(200)
.json({
loginSuccess: true, userId: user._id
});
});
});
});
});