Archive

Auth Boiler Plate with Node.js-Bcrypt 암호화

|

Boiler Plate with Node.js - Bcrypt 암호화


Bcrypt 비밀번호 암호화

bcrypt는 비밀번호 등 노출의 위험이 있는 데이터들을 암호화하는데 필요한 패키지이다

npm i --save bcrypt 설치

DB에 데이터 저장을 위해 save 메소드가 실행되기 전, pre 메소드를 통해 무언가 작업을 할 수 있다

bcrypt 공식문서를 참고하여 코드를 작성한다

여기서 salt라는 중요한 개념이 나온다

비밀번호를 해시 값으로 변환한다하더라도 단순한 단방향 변환은 의미가 없다

salt를 중간에 끼워주어서 비밀번호의 복호화를 더욱 어렵게 하는것이다

// User.js

const bcrypt = require('bcrypt');
const saltRounds = 10;

userSchema.pre('save', function(next){ // save 전 실행
  var user = this; // 현재 스키마에 값이 저장되므로 this로 받음
  // 비밀번호 암호화
  if (user.isModified('password')) { // 분기점
    bcrypt.genSalt(saltRounds, function(err, salt){ // salt 생성, saltRounds 넣고 콜백
      if (err) return next(err);

      bcrypt.hash(user.password, salt, function(err, hash){ // 비번,솔트 넣고 콜백 실행
        if (err) return next(err);
        user.password = hash; // 변환된 hash값을 대입
        next(); // next로 다시 save 단계로 넘어감
      });
    });
  }
});

주의 : this 바인딩 문제로 pre 내에서는 arrow function 사용하면 안된다


성공

postman을 이용해 테스트를 해보면 비밀번호가 정상적으로 암호화된 것을 볼 수 있다!


Login with bcrypt

본격 로그인 기능 만들기

index.js에 post로 클라이언트가 요청한 작업을 수행할 내용을 작성한다

app.post('/login', (req, res) => {
  // 클라가 요청한 이메일을 DB에서 검색
  User.findOne({ email: req.body.email }, (err, user) => {
    if (!user) { // 해당 유저가 없으면
      return res.json({
        loginSuccess: false,
        message: '아이디가 일치하지 않습니다',
      });
    } else {
      // 이메일이 DB에 있으면 비밀번호 대조
      user.comparePassword(req.body.password, (err, isMatch) => {
        if (!isMatch) { // 요청 비번이 일치하지 않으면
          return res.json({
            loginSuccess: false,
            message: '비밀번호가 일치하지 않습니다',
          });
        } else {
          // 비밀번호 맞으면 Token 생성
          user.genToken((err, user) => {}); // 다음 강의 계속
        }
      });
    }
  });
});

위의 comparePassword는 custom method이다

User.js에서 스키마를 이용하여 작성한다

// User.js

userSchema.methods.comparePassword = function (plainPassword, cb) {
  // 요청받은 비밀번호를 암호화 후 DB의 비번과 대조
  bcrypt.compare(plainPassword, this.passowrd, function (err, isMatch) {
    if (err) return cb(err); // isMatch 적지않은 이유는 false기 때문
    cb(null, isMatch);
  });
};

마찬가지로 this 바인딩 문제로 arrow function은 사용하지 않았다

토큰 생성은 다음에 계속~



참고 자료


기초 노드 리액트 강의 - John Ahn