Node.js | React | MongoDB | Express (3)

Tony Kim·2022년 2월 3일
0
post-thumbnail

Node.js | React | MongoDB | Express (3)

1. Bcrypt로 비밀번호 암호화

암호화하는 이유

지난시간 POSTMAN을 통해 개인정보 전송함
mongoDB > databases > browse collection > query results

_id : ObjectId("61f7934f1bccc54aa85990d8")
name : "james123"
email : "james@naver.com"
password : "123123"
role : 0
__v :0

정보 등록되어있지만 보안에 취약
-> 암호화해서 데이터베이스에 저장

순서
1) 다운로드

bycrypt 라이브러리 다운로드

npm install bcrypt --save

2) register router 부분에서 암호화

  • 모든 정보를 model에 넣어주고 난 후 save하기 전에 비밀번호 암호화 필요
  • mongoose 기능 활용
  • usermodel > userschema (in User.js)

bcrypt usage

생성된 salt로 비밀번호 암호화
a) salt 생성 (코드 붙여넣기)
b) salt Rounds (salt가 몇글자인지, default 10)

User.js

const bcrypt = require('bcrypt')
const saltRounds = 10;
userSchema.pre('save', function(next) {
  //비밀번호 암호화
  var user = this;
  if(user.isModified('password')) {  // pw변경시에만 해쉬값 넣도록
    bcrypt.genSalt(saltRounds, function(err, salt) {
      if(err) return next(err) //에러나오면 index로
      bcrypt.hash(user.password, salt, function(err, hash) {
        // Store hash in your password DB.
        if(err) return next(err)
        user.password = hash
        next()  // hash값 저장했으면 index로
      });
    });
  } else {
    next()
  }
})
_id : ObjectId("61fb89f50d659a386d8c72f6")
name : "james3434"
email : "jamedds@naver.com"
password : "$2b$10$9ZGYzAkMClob8UZ3ivcZHObj7a9skF6DIgmU1s7Ml28LLd7LQG0l."
role : 0
__v : 0

2. 로그인 기능 with Bcrypt

로그인 route
a) 요청된 이메일을 데이터베이스에 있는지 찾기
b) 요청한 이메일이 데이터베이스에 있다면 비밀번호 맞는지 확인
c) 토큰 생성하기 (jsonwebtoken 이용)

jsonwebtoken usage

npm install jsonwebtoken --save
npm install cookie-parser --save

index.js

const cookieParser = require('cookie-parser')
app.use(cookieParser());
--------------------------------------------------------------------------------------------
app.post('/login',(req,res) => {
  // 요청된 이메일을 데이터베이스에 있는지 찾기
  User.findOne({email: req.body.email}, (err, user) => {
    if(!user) {
      return res.json({
        loginSuccess: false,
        message: "제공된 이메일에 해당하는 유저가 없습니다."
      })
    }
    // 요청한 이메일이 데이터베이스에 있다면 비밀번호 맞는지 확인
    user.comparePassword(req.body.password, (err, isMatch) => {
      if(!isMatch)
        return res.json({loginSuccess: false, message: "비밀번호가 틀렸습니다."})
      // 토큰 생성하기
      user.generateToken((err, user) => {
        //jsonwebtoken 활용
        if(err) return res.status(400).send(err);
        // 토큰을 저장한다. 어디에? -> 여러곳 가능 [쿠키, 세션, 로컬스토리지]
        // 어디가 가장 안전한지는 사람마다 다름, 로컬, 쿠키 등등
        // 여기서는 쿠키 -> 라이브러리 다운로드 필요 (express에서 제공하는 cookie paraser)
        res.cookie("x_auth", user.token)
        .status(200)
        .json({ loginSuccess: true, userId: user._id })
      })
    })
  })
})

User.js

const bcrypt = require('bcrypt');
const saltRounds = 10;
const jwt = require('jsonwebtoken');
----------------------------------------------------------------------------------------
userSchema.methods.comparePassword = function(plainPassword, cb) {
  // plainPassword 1234567 일 때 암호화된 비밀번호(해쉬값) 비교
  bcrypt.compare(plainPassword, this.password, function(err, isMatch) {
    if(err) return cb(err),
    cb(null, isMatch)
  })
}
-----------------------------------------------------------------------------------------
userSchema.methods.generateToken = function(cb) {
  var user = this; // ES5문법
  //jsonwebtoken이용해서 token생성
  var token = jwt.sign(user._id.toHexString(), 'secretToken') 
  //user._id + 'secretToken' = token
  //_id는 데이터베이스에 저장된 id값
  // -> 'secretToken' -> user_.id 확인가능
  user.token = token
  user.save(function(err, user) {
    if(err) return cb(err)
    cb(null, user)
  })
}
profile
Back-end-dev

0개의 댓글