게시판 - 계정 비밀번호 암호화(bcrypt)

소스코드

이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실행할 수 있습니다.

이 게시물의 소스코드는 게시판 만들기 / 게시판 - 회원가입에서 이어집니다.

board.git 을 clone 한 적이 있는 경우: 터미널에서 해당 폴더로 이동 후 아래 명령어들을 붙여넣기합니다. 폴더 내 모든 코드가 이 게시물의 코드로 교체됩니다. 이를 원치 않으시면 이 방법을 선택하지 마세요.

git reset --hard
git pull
git reset --hard 2af8082
git reset --soft 4adcb08
npm install
atom .

board.git 을 clone 한 적이 없는 경우: 터미널에서 코드를 다운 받을 폴더로 이동한 후 아래 명령어들을 붙여넣기하여 board.git 을 clone 합니다.

git clone https://github.com/a-mean-blogger/board.git
cd board
git reset --hard 2af8082
git reset --soft 4adcb08
npm install
atom .

- Github에서 소스코드 보기: https://github.com/a-mean-blogger/board/tree/2af808210a363112de52a80ad2d781372afc7415


이전 강의에서 user CURD를 사용해 회원가입 기능을 만들어 보았습니다. 여기서 user의 비밀번호가 그대로 DB에 저장되는데 비밀번호는 반드시 hash처리가 되어야 합니다.

** Hash에 대해 잘 모르시는 분들은 반드시 토막글Hash를 먼저 읽고 계속 진행해 주세요.

이 포스팅에서는 bcrypt-nodejs package를 사용해서 DB에 password 를 hash로 변환하여 저장하는 방법을 알아 봅시다.

이번 강의를 통해서 password가 hash되면 이전에 생성된 user들은 더이상 사용이 불가능합니다. 이번 강의를 시작하기 전에 이전강의의 테스트를 위해 생성된 user들은 모두 삭제해 주세요.

폴더구조

Package 설치

$ npm install --save bcrypt-nodejs

코드

// models/User.js

var mongoose = require('mongoose');
var bcrypt = require('bcrypt-nodejs'); // 1

...

  // update user
  if(!user.isNew){
    if(!user.currentPassword){
      user.invalidate('currentPassword', 'Current Password is required!');
    }
    else if(!bcrypt.compareSync(user.currentPassword, user.originalPassword)){ // 2
      user.invalidate('currentPassword', 'Current Password is invalid!');
    }

    ...

// hash password // 3
userSchema.pre('save', function (next){
  var user = this;
  if(!user.isModified('password')){ // 3-1
    return next();
  }
  else {
    user.password = bcrypt.hashSync(user.password); //3-2
    return next();
  }
});

// model methods // 4
userSchema.methods.authenticate = function (password) {
  var user = this;
  return bcrypt.compareSync(password,user.password);
};

...

1. require함수로 bcrypt-nodejs pacakge를 bcrypt 변수에 담았습니다.

2. bcrypt 의 compareSync함수를 사용해서 저장된 hash와 입력받은 password의 hash가 일치하는지 확인합니다.
bcrypt.compareSync(user.currentPassword, user.originalPassword)에서 user.currentPassword는 입력받은 text값이고 user.originalPassword는 user의 password hash값입니다. hash를 해독해서 text를 비교하는것이 아니라 text값을 hash로 만들고 그 값이 일치하는 지를 확인하는 과정입니다.

3. Schema.pre함수는 첫번째 파라미터로 설정된 event가 일어나기 전(pre)에 먼저 callback 함수를 실행시킵니다.
"save" event는 Model.create, model.save 함수 실행시 발생하는 event입니다.
user를 생성하거나 user를 수정한 뒤 save 함수를 실행 할 때 위의 callback 함수가 먼저 호출됩니다.

3-1. isModified함수는 해당 값이 db에 기록된 값과 비교해서 변경된 경우 true를, 그렇지 않은 경우 false를 반환하는 함수입니다. user 생성시는 항상 true이며, user 수정시는 password가 변경되는 경우에만 true를 반환합니다.
user.password의 변경이 없는 경우라면 이미 해당위치에 hash가 저장되어 있으므로 다시 hash를 만들지 않습니다.

3-2. user를 생성하거나 user수정시 user.password의 변경이 있는 경우에는 bcrypt.hashSync함수로 password를 hash값으로 바꿉니다.

4. user model의 password hash와 입력받은 password text를 비교하는 method를 추가합니다. 이번 예제에 사용되는 method는 아니고 나중에 로그인을 만들때 될 method인데 bcrypt를 사용하므로 지금 추가해봤습니다.

실행결과

코드의 실행결과는 이전과 같습니다. 사용자는 뭐가 달라졌는지 전혀 알 수 없죠.

마치며...

이번 강의는 내용이 짧습니다. 이전 강의에서 '비밀번호 인증'이라는 것이 DB의 password와 입력받은 password를 비교하는 것뿐임을 보여주고 싶었기 때문에 일부러 분리를 했습니다.

댓글

댓글쓰기

이 글에 댓글을 다시려면 SNS 계정으로 로그인하세요. 자세히 알아보기

UP