티스토리 뷰

728x90
반응형

bcypt(비크립트)는 블로피시 암호에 기반을 둔 암호화 해시 함수다.

 

암호화는 비밀번호를 노출되지 않도록 해시값으로 변경하여 저장을 하는 것인데, 여기서는 회원가입 시 저장하기 전에 변경을 하는데에 bcrypt 라이브러리를 사용한다.

userSchema.pre('save', (next) => {});

userSchema가 호출되는 라우터가 있을 때, 그전에 먼저 pre미들웨어를 실행을 해준다. 그리고 next를 하면 스키마를 호출한 곳으로 돌아간다.

 

 

const userSchema = mongoose.Schema(
	...
);
userSchema.pre('save', (next) => {
	var user = this;
});

여기서 var user = this는 userSchema 자기 자신을 가리킨다.

 

 

const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const saltRounds = 10;
const jwt = require('jsonwebtoken');

const userSchema = mongoose.Schema(
	...
);

userSchema.pre('save', (next) => {
	var user = this;
  
	bcrypt.genSalt(saltRounds, (err, salt) => {
        if(err) return  next(err)
    	bcrypt.hash(user.password, salt, (err, has) => {
        ...
        });
    });
});

여기서 bcrypt.gensalt에서 에러가 발생하였을 때 스키마를 호출한 곳으로 바로 에러와 함께 넘어간다. salt생성이 제대로 되었을 경우 아래 bcrypt.hash로 넘어간다.

user.password는 사용자가 직접 입력한 비밀번호를 의미한다.

 

그렇게 완성된 코드는 다음과 같다.

const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const saltRounds = 10;
const jwt = require('jsonwebtoken');

const userSchema = mongoose.Schema(
  {
    nickname: String,
    email: {
      type: String,
      trim: true,
      unique: true,
    },
    password: String,
    role: {
      type: Number,
      default: 0,
    },
    token: String,
    tokenExp: Number,
  },
  { collection: 'users' },
);

userSchema.pre('save', (next) => {
  var user = this;

  bcrypt.genSalt(saltRounds, (err, salt) => {
    if(err) return  next(err)
    bcrypt.hash(user.password, salt, (err, has) => {
     if (err) return next(err);
      user.password = hash;
      next();
    });
  });
});

const User = mongoose.model('User', userSchema);

module.exports = { User };

여기까지 했을 경우 유저가 회원가입을 했을 때 비밀번호를 해쉬로 변경해서 저장을 할 수 있도록 해주었다.

 

 

하지만 이름, 이메일, 비밀번호를 바꾸는 경우가 종종 있다. 이때 계속 해쉬값을 변경을 하면 안 되고, 비밀번호를 바꿀 때에만 변경을 가능하도록 해주는 기능을 추가하려고 한다.

userSchema.pre('save', (next) => {
  var user = this;

  if (user.isModified('password')) {
    bcrypt.genSalt(saltRounds, (err, salt) => {
      if (err) return next(err);
      bcrypt.hash(user.password, salt, (err, hash) => {
        if (err) return next(err);
        user.password = hash;
        next();
      });
    });
  }
});

여기서 isModified는 주어진 경로 중 하나라도 수정이 되면 true를 반환을 하고 그렇지 않으면 false를 반환을 해준다. 여기서는 password가 수정이 되었을 때에만 비밀번호 암호화를 실행해준다는 의미를 가진다.

 

참고 문서 몽구스 isModified 바로가기

 

그러면 회원가입 시 비밀번호를 DB에 바로 저장이 되지 않는 것을 알 수 있다.

 

필자는 실제 테스트 결과 몇가지 오류를 발견했다.

회원가입시 서버에러

서버에서 isModified는 함수가 아니다 라는 에러를 발견했고 찾아보니까 다음과 같은 내용이 있다.

에러 해결방법 출처 stackoverflow

화살표 함수를 쓰면 this의 범위가 바뀌기 때문에 isModified를 쓸 때는 function으로 사용해야 한다고 한다.

몽구스에서의 tihs의 의미

또한 몽구스의 미들웨어를 사용할때에는 this는 쿼리이기 때문에 위 이미지와 같이 해야 한다고 한다.

그래서 필자는 일단 해당 코드만 function으로 변경을 했다.

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();
      });
    });
  }
});

 

공식문서를 찾아보니까. 화살표 함수는 this에 대한 바인딩이 없다.라는 문구가 있다는데...

아직은 이해가 잘 되지 않네요.. 이 부분은 더 찾아봐야 할 듯 하다...

 

화살표 함수 공식 문서

 

이 부분은 조금 더 후에 다시 찾아보는 걸로...

728x90
반응형
댓글
250x250
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함